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.
- {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/METADATA +4 -4
- {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/RECORD +61 -60
- pytcl/__init__.py +2 -2
- pytcl/assignment_algorithms/gating.py +18 -0
- pytcl/assignment_algorithms/jpda.py +56 -0
- pytcl/assignment_algorithms/nd_assignment.py +65 -0
- pytcl/assignment_algorithms/network_flow.py +40 -0
- pytcl/astronomical/ephemerides.py +18 -0
- pytcl/astronomical/orbital_mechanics.py +131 -0
- pytcl/atmosphere/ionosphere.py +44 -0
- pytcl/atmosphere/models.py +29 -0
- pytcl/clustering/dbscan.py +9 -0
- pytcl/clustering/gaussian_mixture.py +20 -0
- pytcl/clustering/hierarchical.py +29 -0
- pytcl/clustering/kmeans.py +9 -0
- pytcl/coordinate_systems/conversions/geodetic.py +46 -0
- pytcl/coordinate_systems/conversions/spherical.py +35 -0
- pytcl/coordinate_systems/rotations/rotations.py +147 -0
- pytcl/core/__init__.py +16 -0
- pytcl/core/maturity.py +346 -0
- pytcl/core/optional_deps.py +1 -1
- pytcl/dynamic_estimation/gaussian_sum_filter.py +55 -0
- pytcl/dynamic_estimation/imm.py +29 -0
- pytcl/dynamic_estimation/information_filter.py +64 -0
- pytcl/dynamic_estimation/kalman/extended.py +56 -0
- pytcl/dynamic_estimation/kalman/linear.py +69 -0
- pytcl/dynamic_estimation/kalman/unscented.py +81 -0
- pytcl/dynamic_estimation/particle_filters/bootstrap.py +146 -0
- pytcl/dynamic_estimation/rbpf.py +51 -0
- pytcl/dynamic_estimation/smoothers.py +58 -0
- pytcl/dynamic_models/continuous_time/dynamics.py +104 -0
- pytcl/dynamic_models/discrete_time/coordinated_turn.py +6 -0
- pytcl/dynamic_models/discrete_time/singer.py +12 -0
- pytcl/dynamic_models/process_noise/coordinated_turn.py +46 -0
- pytcl/dynamic_models/process_noise/polynomial.py +6 -0
- pytcl/dynamic_models/process_noise/singer.py +52 -0
- pytcl/gravity/clenshaw.py +60 -0
- pytcl/gravity/egm.py +47 -0
- pytcl/gravity/models.py +34 -0
- pytcl/gravity/spherical_harmonics.py +73 -0
- pytcl/gravity/tides.py +34 -0
- pytcl/mathematical_functions/numerical_integration/quadrature.py +85 -0
- pytcl/mathematical_functions/special_functions/bessel.py +55 -0
- pytcl/mathematical_functions/special_functions/elliptic.py +42 -0
- pytcl/mathematical_functions/special_functions/error_functions.py +49 -0
- pytcl/mathematical_functions/special_functions/gamma_functions.py +43 -0
- pytcl/mathematical_functions/special_functions/lambert_w.py +5 -0
- pytcl/mathematical_functions/special_functions/marcum_q.py +16 -0
- pytcl/navigation/geodesy.py +101 -2
- pytcl/navigation/great_circle.py +71 -0
- pytcl/navigation/rhumb.py +74 -0
- pytcl/performance_evaluation/estimation_metrics.py +70 -0
- pytcl/performance_evaluation/track_metrics.py +30 -0
- pytcl/static_estimation/maximum_likelihood.py +54 -0
- pytcl/static_estimation/robust.py +57 -0
- pytcl/terrain/dem.py +69 -0
- pytcl/terrain/visibility.py +65 -0
- pytcl/trackers/hypothesis.py +65 -0
- {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/LICENSE +0 -0
- {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/WHEEL +0 -0
- {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: nrl-tracker
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2
|
|
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
|
|
@@ -63,17 +63,17 @@ Requires-Dist: plotly>=5.15.0; extra == "visualization"
|
|
|
63
63
|
|
|
64
64
|
# Tracker Component Library (Python)
|
|
65
65
|
|
|
66
|
-
[](https://pypi.org/project/nrl-tracker/)
|
|
67
67
|
[](https://www.python.org/downloads/)
|
|
68
68
|
[](https://en.wikipedia.org/wiki/Public_domain)
|
|
69
69
|
[](https://github.com/psf/black)
|
|
70
|
-
[](https://github.com/nedonatelli/TCL)
|
|
71
71
|
[](docs/gap_analysis.rst)
|
|
72
72
|
[](mypy.ini)
|
|
73
73
|
|
|
74
74
|
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.
|
|
75
75
|
|
|
76
|
-
**1,070+ functions** | **153 modules** | **
|
|
76
|
+
**1,070+ functions** | **153 modules** | **2,133 tests** | **100% MATLAB parity**
|
|
77
77
|
|
|
78
78
|
## Overview
|
|
79
79
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
pytcl/__init__.py,sha256=
|
|
1
|
+
pytcl/__init__.py,sha256=7ROietZU-pUiPRpioyeMjjZ6XybbmjRs1qRR_KoXioQ,2030
|
|
2
2
|
pytcl/logging_config.py,sha256=UJaYufQgNuIjpsOMTPo3ewz1XCHPk8a08jTHyP7uoI4,8956
|
|
3
3
|
pytcl/assignment_algorithms/__init__.py,sha256=kUWhmyLhZcs5GiUQA5_v7KA3qETGsvqV6wU8r7paO-k,2976
|
|
4
4
|
pytcl/assignment_algorithms/data_association.py,sha256=tsRxWJZk9aAPmE99BKXGouEpFfZrjPjb4HXvgxFUHhU,11405
|
|
5
5
|
pytcl/assignment_algorithms/dijkstra_min_cost.py,sha256=z-Wk1HXRNKieBsRFqR8_UB8QvG5QkK3evazr8wzTpl0,5429
|
|
6
|
-
pytcl/assignment_algorithms/gating.py,sha256=
|
|
7
|
-
pytcl/assignment_algorithms/jpda.py,sha256=
|
|
8
|
-
pytcl/assignment_algorithms/nd_assignment.py,sha256=
|
|
9
|
-
pytcl/assignment_algorithms/network_flow.py,sha256=
|
|
6
|
+
pytcl/assignment_algorithms/gating.py,sha256=JaRaFcFqjfdsTbbTP6k_GY2zemDSR02l5yInWHpb05Y,11439
|
|
7
|
+
pytcl/assignment_algorithms/jpda.py,sha256=rOY_v1vesL6EJySwD0kRDTfe7wHoDFLITg_lJLM-bX4,21731
|
|
8
|
+
pytcl/assignment_algorithms/nd_assignment.py,sha256=qYTFZryqfnHXz1I1Kg2vTvEJIYla4JknedhKPXphdiQ,13269
|
|
9
|
+
pytcl/assignment_algorithms/network_flow.py,sha256=pPD63Z0-HOBv5XIqKUedt1KzTkcs0KG41DNojFZocDI,14459
|
|
10
10
|
pytcl/assignment_algorithms/network_simplex.py,sha256=Qi10PsIYcTc6MZ-9GPl6ivaLaGA9F5-B7ltBbmasRNM,5566
|
|
11
11
|
pytcl/assignment_algorithms/three_dimensional/__init__.py,sha256=1Q40OUlUQoo7YKEucwdrSNo3D4A0Zibvkr8z4TpueBg,526
|
|
12
12
|
pytcl/assignment_algorithms/three_dimensional/assignment.py,sha256=OGcjg3Yr1tYriWYBJ5k6jiRMpOHDISK8FJDY0nTQxxw,19244
|
|
@@ -14,9 +14,9 @@ pytcl/assignment_algorithms/two_dimensional/__init__.py,sha256=4Evsn__9hTfI2i8m8
|
|
|
14
14
|
pytcl/assignment_algorithms/two_dimensional/assignment.py,sha256=eh87MBb-uiUSI1MXj4HrreRKB6Z8rxAyDkNQ8-u4SbM,11848
|
|
15
15
|
pytcl/assignment_algorithms/two_dimensional/kbest.py,sha256=yiTToLuP7xWxQlQ8E-fpgXg-5iu0nnXcJXStjUB0nOE,17284
|
|
16
16
|
pytcl/astronomical/__init__.py,sha256=v0nUgEy5ReHXzpNb1JdwWXv4AtcFksotEOccQnOyVfI,9667
|
|
17
|
-
pytcl/astronomical/ephemerides.py,sha256=
|
|
17
|
+
pytcl/astronomical/ephemerides.py,sha256=cZ_qedKAG7BfIinjfGyH48pRwiVfn7bQ_4qyICa9-GA,17401
|
|
18
18
|
pytcl/astronomical/lambert.py,sha256=Lc8FT1JmpI9WSXsG2s5vIRkSoBSV7r5hd3o2bGh2Ojo,15607
|
|
19
|
-
pytcl/astronomical/orbital_mechanics.py,sha256=
|
|
19
|
+
pytcl/astronomical/orbital_mechanics.py,sha256=alC8r9SToqVpBeo6EJ6alHdoJ6hJ6wshZF_xA1qPYJQ,23003
|
|
20
20
|
pytcl/astronomical/reference_frames.py,sha256=MBqprzBpEvdq3ngRL-_pp-Vnj7AqbuXhjUfGQ98znfc,35616
|
|
21
21
|
pytcl/astronomical/relativity.py,sha256=vSay4am_ElkiGRwuu_4rwo5C10eN8hm86jy43xmaEt4,15933
|
|
22
22
|
pytcl/astronomical/sgp4.py,sha256=iNZrqMRUzR-LFeZiluzlNmkwxeYbIyF2F1cygyeEZVE,21546
|
|
@@ -24,14 +24,14 @@ pytcl/astronomical/special_orbits.py,sha256=N54c_wAD7XKk_diDOw2QjUSkmYECMyWQDq2P
|
|
|
24
24
|
pytcl/astronomical/time_systems.py,sha256=Jg0Zaq60hc4Ts1aQtb5bK4KSZhz-uQse8gYC89Y0-TA,15243
|
|
25
25
|
pytcl/astronomical/tle.py,sha256=t3e2-0f3Wiz77q-pC2jfpohkrDfoYOEHacpNgWMNLAk,14638
|
|
26
26
|
pytcl/atmosphere/__init__.py,sha256=Joa6PBEfKun0Moii6BOzyVYG8AOFyvucKdVuY62ArQc,1685
|
|
27
|
-
pytcl/atmosphere/ionosphere.py,sha256=
|
|
28
|
-
pytcl/atmosphere/models.py,sha256=
|
|
27
|
+
pytcl/atmosphere/ionosphere.py,sha256=tt_Qu1IvqZxah2P_QaWxpwroSgtDNU-6RrqtxMRZScY,16092
|
|
28
|
+
pytcl/atmosphere/models.py,sha256=ZAwa6rsSe9RaQyVjiJ2i2K_D9ZyJ0MymhSsltnsiAK8,10358
|
|
29
29
|
pytcl/atmosphere/nrlmsise00.py,sha256=jcmAC00G3X0CzfK4eWkvq2tPxHXzMqC8GBHNbFZRq4w,25868
|
|
30
30
|
pytcl/clustering/__init__.py,sha256=bYdhC_XJEt6KUUni9bIPxaddXNEGmIJQvGkA14rK4J8,1697
|
|
31
|
-
pytcl/clustering/dbscan.py,sha256=
|
|
32
|
-
pytcl/clustering/gaussian_mixture.py,sha256=
|
|
33
|
-
pytcl/clustering/hierarchical.py,sha256=
|
|
34
|
-
pytcl/clustering/kmeans.py,sha256=
|
|
31
|
+
pytcl/clustering/dbscan.py,sha256=paEua1ocHfnEM1rh972osfKPerziSw04vRkRmNApb1U,7681
|
|
32
|
+
pytcl/clustering/gaussian_mixture.py,sha256=U-mIRLkpyZbWt9Egx3CZrpDCmci9588YMVff0JM8ge0,23778
|
|
33
|
+
pytcl/clustering/hierarchical.py,sha256=MDBIcJtZHYruSsM_seAR9bNWKB63EDh1nIf6qAn43lE,15195
|
|
34
|
+
pytcl/clustering/kmeans.py,sha256=_r08KVvqHL1UnYE4rHBAJ1OKA97q-PWl2OOsTi6kKqk,10963
|
|
35
35
|
pytcl/containers/__init__.py,sha256=i-o_KDjhbPWc9yAlgN1R5igmyWK3CVKIB-V7Qnr-fLg,2746
|
|
36
36
|
pytcl/containers/base.py,sha256=oKD8vAH09qAEOG3uhtoTgJ9UU_hQhl6keSIlGEVucrs,7762
|
|
37
37
|
pytcl/containers/cluster_set.py,sha256=uhfOIpXlYoI1U75TWcLMHjezVavnIZhVEGQHKCDmKo4,22774
|
|
@@ -43,58 +43,59 @@ pytcl/containers/track_list.py,sha256=6q9Qgcwm-8H_JqtOCsMssF27av4XaSkhfDl-MWb1AB
|
|
|
43
43
|
pytcl/containers/vptree.py,sha256=-7znAilGCNpN7SN8TxVhNFIOyP-s9oJa9Vp4FJWehcg,8720
|
|
44
44
|
pytcl/coordinate_systems/__init__.py,sha256=jwYhu_-9AvOeP9WLG9PYtyDwfe0GjxNZ9-xCqiLymW4,3909
|
|
45
45
|
pytcl/coordinate_systems/conversions/__init__.py,sha256=PkNevB78vBw0BkalydJBbQO91AyiMJxKRrgJNt4HsYc,1100
|
|
46
|
-
pytcl/coordinate_systems/conversions/geodetic.py,sha256=
|
|
47
|
-
pytcl/coordinate_systems/conversions/spherical.py,sha256=
|
|
46
|
+
pytcl/coordinate_systems/conversions/geodetic.py,sha256=CarrTBW9rTC-CZ4E4YGxA8QjlpauuXJ2ZScnzc4QvK8,25001
|
|
47
|
+
pytcl/coordinate_systems/conversions/spherical.py,sha256=GwuS1k0aUQ3AG1zZJouioMjxSIuEPRZMk-arvUCTh2k,11563
|
|
48
48
|
pytcl/coordinate_systems/jacobians/__init__.py,sha256=CRGB8GzvGT_sr4Ynm51S7gSX8grqt1pO1Pq1MWmHPTs,890
|
|
49
49
|
pytcl/coordinate_systems/jacobians/jacobians.py,sha256=0gpbelZPN4HDtvS1ymc3RIhOfxCVTKpRc-jDJXdM6pQ,11747
|
|
50
50
|
pytcl/coordinate_systems/projections/__init__.py,sha256=TmBiffO5cmazAhsfPIVBaaqnravVSO3JxjGb0MXkucc,2404
|
|
51
51
|
pytcl/coordinate_systems/projections/projections.py,sha256=y_kwcu_zp0HHiKR-wp3v3AvRcY61bleDi1SxwbrnWB0,33179
|
|
52
52
|
pytcl/coordinate_systems/rotations/__init__.py,sha256=nqAz4iJd2hEOX_r7Tz4cE524sShyxdbtcQ5m56RrDLg,1047
|
|
53
|
-
pytcl/coordinate_systems/rotations/rotations.py,sha256
|
|
54
|
-
pytcl/core/__init__.py,sha256=
|
|
53
|
+
pytcl/coordinate_systems/rotations/rotations.py,sha256=-VheczqsqF-qHF46HVKYTe0oS76MTmqyXQV3EO2JAJs,22258
|
|
54
|
+
pytcl/core/__init__.py,sha256=Rm02KyEP5jCgcaS6N6F-Bs2nLgW-EO1cjCD0NqAg664,3236
|
|
55
55
|
pytcl/core/array_utils.py,sha256=SsgEiAoRCWxAVKq1aa5-nPdOi-2AB6XNObu0IaGClUk,13983
|
|
56
56
|
pytcl/core/constants.py,sha256=cwkCjzCU7zG2ZsFcbqwslN632v7Lw50L85s-5q892mo,9988
|
|
57
57
|
pytcl/core/exceptions.py,sha256=6ImMiwL86BdmTt-Rc8fXLXxKUGQ-PcQQyxIvKKzw-n0,24324
|
|
58
|
-
pytcl/core/
|
|
58
|
+
pytcl/core/maturity.py,sha256=Sut19NfH1-6f3Qd2QSC6OAqvDcVHJDwf5-F_-oEAMJA,11596
|
|
59
|
+
pytcl/core/optional_deps.py,sha256=Xe7BG18SWsmzBD3zGa440U_QWKkfATBKhUfLOxhXZuU,15799
|
|
59
60
|
pytcl/core/validation.py,sha256=4ay21cZVAil8udymwej7QnVQfNyjzi_5A8O1y-d-Lyw,23492
|
|
60
61
|
pytcl/dynamic_estimation/__init__.py,sha256=zxmkZIXVfHPv5AHYpQV5nwsI0PA3m-Vw7W0gkJE7j98,5191
|
|
61
|
-
pytcl/dynamic_estimation/gaussian_sum_filter.py,sha256=
|
|
62
|
-
pytcl/dynamic_estimation/imm.py,sha256=
|
|
63
|
-
pytcl/dynamic_estimation/information_filter.py,sha256=
|
|
64
|
-
pytcl/dynamic_estimation/rbpf.py,sha256=
|
|
65
|
-
pytcl/dynamic_estimation/smoothers.py,sha256=
|
|
62
|
+
pytcl/dynamic_estimation/gaussian_sum_filter.py,sha256=3Ks5-sGo3IF9p_dsIzk5u2zaXS2ZAkJFAg1mdxo8vj8,15343
|
|
63
|
+
pytcl/dynamic_estimation/imm.py,sha256=Iq8hpnak9NQxcrtIoYgFYReul3sjo8o3QOvr9vXXUEU,23258
|
|
64
|
+
pytcl/dynamic_estimation/information_filter.py,sha256=DIziISqxbhfmLaeK5T6zROhncTZQKm4d3077nfs5u6o,19254
|
|
65
|
+
pytcl/dynamic_estimation/rbpf.py,sha256=gaJz0fDCFf-VAIQHlqrpFGv5LsBQMlr0DfptSv4JpQw,19819
|
|
66
|
+
pytcl/dynamic_estimation/smoothers.py,sha256=QVThB1E8Tj8UFHMRJ4tNMq509SvvBHECQRlMSM5fjRg,21259
|
|
66
67
|
pytcl/dynamic_estimation/batch_estimation/__init__.py,sha256=JQ0s76Enov5a7plA4EnUua4t-7etikQrwr5z4WIjUeo,46
|
|
67
68
|
pytcl/dynamic_estimation/kalman/__init__.py,sha256=lR-OacfZ5mqnAboEbOel5w_WS_Gmz-1q0l4meKfQsGs,3163
|
|
68
69
|
pytcl/dynamic_estimation/kalman/constrained.py,sha256=Zidzz6_9OvwUyQppEltdmYTMvEeqRKFRkVMwx1TASuw,10960
|
|
69
|
-
pytcl/dynamic_estimation/kalman/extended.py,sha256=
|
|
70
|
+
pytcl/dynamic_estimation/kalman/extended.py,sha256=Yxc4Ve2aBtrkoelfMTFmzcXZefVZM0p0Z_a9n2IM1gQ,12032
|
|
70
71
|
pytcl/dynamic_estimation/kalman/h_infinity.py,sha256=rtbYiryJbxzko-CIdNJSHuWXU2wI9T52YGBYq3o92sE,16563
|
|
71
|
-
pytcl/dynamic_estimation/kalman/linear.py,sha256=
|
|
72
|
+
pytcl/dynamic_estimation/kalman/linear.py,sha256=gLFoCHjWtNHus_Nh4fTu67n_Xiv9QFVAuO5vO8MJICo,14673
|
|
72
73
|
pytcl/dynamic_estimation/kalman/matrix_utils.py,sha256=couRVm0VKbhj9ctHcI-wcq8rj2MOapaSRVGuVdze3fQ,12426
|
|
73
74
|
pytcl/dynamic_estimation/kalman/square_root.py,sha256=RlDepNt7eJ1qbQkZElqfhcX2oJET09P9Q_P8Bv7LcJo,8199
|
|
74
75
|
pytcl/dynamic_estimation/kalman/sr_ukf.py,sha256=Vys5uC58HSZSTLc9xfmWCjw_XnZZfD4MpFBXBX0OVzU,8912
|
|
75
76
|
pytcl/dynamic_estimation/kalman/types.py,sha256=5sMEWAvd9kkE3EG9daYcG8uV70MBx_awC5u6KJkmiZw,2202
|
|
76
77
|
pytcl/dynamic_estimation/kalman/ud_filter.py,sha256=j56gw-piKJaMtoHWRkr2MiBjOC9tGSguIgFregOMJOs,10269
|
|
77
|
-
pytcl/dynamic_estimation/kalman/unscented.py,sha256=
|
|
78
|
+
pytcl/dynamic_estimation/kalman/unscented.py,sha256=I88b2XVAoiKlOnmNrI4vc3hAbHMc_sILmqXu2t4JktQ,17777
|
|
78
79
|
pytcl/dynamic_estimation/measurement_update/__init__.py,sha256=8rlyJwVpxf0fZj-AFo1hlewvryZRhUzcy3F8uMe6I8c,48
|
|
79
80
|
pytcl/dynamic_estimation/particle_filters/__init__.py,sha256=-DRF5rVF2749suLlArmkTvVkqeMcV_mIx0eLeTj6wNU,906
|
|
80
|
-
pytcl/dynamic_estimation/particle_filters/bootstrap.py,sha256=
|
|
81
|
+
pytcl/dynamic_estimation/particle_filters/bootstrap.py,sha256=MZlBTO7lYQprireUS52O1dxtL4srrPylFT3BoIU8Jrw,18187
|
|
81
82
|
pytcl/dynamic_models/__init__.py,sha256=Cd8MyyYuB8gMnepkPA-HSwTaKFPThnqoKOhdjVOsXWg,2783
|
|
82
83
|
pytcl/dynamic_models/continuous_time/__init__.py,sha256=dAkfEddLkfMvDalK9v2GRBvaZV1KgqYpFBLOnoiFClw,1023
|
|
83
|
-
pytcl/dynamic_models/continuous_time/dynamics.py,sha256=
|
|
84
|
+
pytcl/dynamic_models/continuous_time/dynamics.py,sha256=X4mmskbj_ngDTWC3eiBuSauqMDFUBXGsNNlB6Q5AuKQ,15718
|
|
84
85
|
pytcl/dynamic_models/discrete_time/__init__.py,sha256=1cdYeVIe-kgogiHzeCv1eYMctSimh8t1nIE6Z1N4im4,949
|
|
85
|
-
pytcl/dynamic_models/discrete_time/coordinated_turn.py,sha256=
|
|
86
|
+
pytcl/dynamic_models/discrete_time/coordinated_turn.py,sha256=h83OUxUeYHdoS2tXcOYtaUe_9tAIe3z1fCJ7-z6yPCw,7322
|
|
86
87
|
pytcl/dynamic_models/discrete_time/polynomial.py,sha256=zv5V-AbuaXlIj36n-YkOEyC74jV2vczxpCW09P0kmi0,5529
|
|
87
|
-
pytcl/dynamic_models/discrete_time/singer.py,sha256=
|
|
88
|
+
pytcl/dynamic_models/discrete_time/singer.py,sha256=o0nR1MJjVi6Qjd5oLsy4vFUgfMKjG3UbE_FIi2qxl8s,4051
|
|
88
89
|
pytcl/dynamic_models/process_noise/__init__.py,sha256=ZRYgV40qmBkPwU3yTbIMvxorr4nVz0_FEP2oCeVjXoM,933
|
|
89
|
-
pytcl/dynamic_models/process_noise/coordinated_turn.py,sha256=
|
|
90
|
-
pytcl/dynamic_models/process_noise/polynomial.py,sha256=
|
|
91
|
-
pytcl/dynamic_models/process_noise/singer.py,sha256=
|
|
90
|
+
pytcl/dynamic_models/process_noise/coordinated_turn.py,sha256=0PciDXtXHjgQdaYf7qpQqIZ7qoMV4uO_kE7wjpiBe64,6483
|
|
91
|
+
pytcl/dynamic_models/process_noise/polynomial.py,sha256=w5ZW5Ouw6QpVtev_mnuCmZoj6_O6ovb2L_ENKDhHYIc,7742
|
|
92
|
+
pytcl/dynamic_models/process_noise/singer.py,sha256=ozAdzH4s0wGlBaxajdyZvSnK8_CumgsUZDKeMW-TxDs,5735
|
|
92
93
|
pytcl/gravity/__init__.py,sha256=5xNdQSrrkt7-1-JPOYqR38CqvNJ7qKlPyMK36DGm6-I,3693
|
|
93
|
-
pytcl/gravity/clenshaw.py,sha256=
|
|
94
|
-
pytcl/gravity/egm.py,sha256=
|
|
95
|
-
pytcl/gravity/models.py,sha256=
|
|
96
|
-
pytcl/gravity/spherical_harmonics.py,sha256=
|
|
97
|
-
pytcl/gravity/tides.py,sha256=
|
|
94
|
+
pytcl/gravity/clenshaw.py,sha256=O7yYfjHMigR1RQHR_gZe3UuMIe_WsGrXFSLzn7PLfIE,16985
|
|
95
|
+
pytcl/gravity/egm.py,sha256=LAeNbaQ7eZakk0ciwLec0_8q41MrBFouVLpDsETis6o,19683
|
|
96
|
+
pytcl/gravity/models.py,sha256=WqBwaOhQdGMx7MsYGYYNbwQLj8rgV-I_VhKZLFvmfso,11990
|
|
97
|
+
pytcl/gravity/spherical_harmonics.py,sha256=bRUFVLgPQEJ8M5a_cJrJ-d5s5xTCmOs4fwRvdYaACuw,18522
|
|
98
|
+
pytcl/gravity/tides.py,sha256=NjsiXSiI7f-0qGr7G7YJVpIOVGzDxagz2S2vf_aRq68,28681
|
|
98
99
|
pytcl/magnetism/__init__.py,sha256=pBASOzCPHNnYqUH_XDEblhGtjz50vY9uW2KS25A0zQQ,2701
|
|
99
100
|
pytcl/magnetism/emm.py,sha256=iIdxSL0uGGIf8nfA-c_SmHvg9_J7HwRA2-qbQIUW6IE,22380
|
|
100
101
|
pytcl/magnetism/igrf.py,sha256=3g0PsH8IdbwQQS28OR5XWD-g-QxvfUva7jOkKToxndQ,13384
|
|
@@ -111,21 +112,21 @@ pytcl/mathematical_functions/geometry/geometry.py,sha256=iLKqTlLEGm8IScEDHEWOBQz
|
|
|
111
112
|
pytcl/mathematical_functions/interpolation/__init__.py,sha256=lK4Rs0Ds_fzf9q0n6id5epdN0U8V7yD87dS-w1hvN8I,741
|
|
112
113
|
pytcl/mathematical_functions/interpolation/interpolation.py,sha256=2cXMDgWBjWDGHnK1K_lawFlJL8oPl5AQGf9MNgsESfo,12610
|
|
113
114
|
pytcl/mathematical_functions/numerical_integration/__init__.py,sha256=iXiHzyV_KIhCv7tXErXlN1_fUEACN6yN3CYDHRA7esw,974
|
|
114
|
-
pytcl/mathematical_functions/numerical_integration/quadrature.py,sha256=
|
|
115
|
+
pytcl/mathematical_functions/numerical_integration/quadrature.py,sha256=F5y8UQltTiAyIj_lGuuRYnSf465Rm_DNHMeq-E8bj-8,17732
|
|
115
116
|
pytcl/mathematical_functions/polynomials/__init__.py,sha256=WJWZcoQhnvy5f59-kncMTgD9mCtgwfDgULvDYYHS5ys,43
|
|
116
117
|
pytcl/mathematical_functions/signal_processing/__init__.py,sha256=_SzzBVtxmSvP8FKeogRdNmFo8FOVDDoexVOqd-lE7do,2325
|
|
117
118
|
pytcl/mathematical_functions/signal_processing/detection.py,sha256=vLToMHdPkhom6ouo1oN0QqBYjEGv7SQENqTD0DOv1XY,30934
|
|
118
119
|
pytcl/mathematical_functions/signal_processing/filters.py,sha256=xiB8VSFqTFkBCAom0yIWw7pK3Zjm6l-VZ_DAtwJMxFA,23676
|
|
119
120
|
pytcl/mathematical_functions/signal_processing/matched_filter.py,sha256=El7XcUbunmXA7s-btXX_R4fgNx8d6QNa86GJETg4zAQ,23134
|
|
120
121
|
pytcl/mathematical_functions/special_functions/__init__.py,sha256=AJBCKj32daQxdahUQckW0bWowzOoapxni2eZnVXERdg,3859
|
|
121
|
-
pytcl/mathematical_functions/special_functions/bessel.py,sha256=
|
|
122
|
+
pytcl/mathematical_functions/special_functions/bessel.py,sha256=kRRPafQMXmooBglEteccjb6Hct1LLq3Oze4JfLQ-AmY,15459
|
|
122
123
|
pytcl/mathematical_functions/special_functions/debye.py,sha256=eH7Y5qq5j-AMKKx7y8uMS_l_pb6z9_3SG6Igvnc1Fdg,9626
|
|
123
|
-
pytcl/mathematical_functions/special_functions/elliptic.py,sha256=
|
|
124
|
-
pytcl/mathematical_functions/special_functions/error_functions.py,sha256=
|
|
125
|
-
pytcl/mathematical_functions/special_functions/gamma_functions.py,sha256=
|
|
124
|
+
pytcl/mathematical_functions/special_functions/elliptic.py,sha256=mF3hVrErlK376pw-QZDoq_R6y8gnJAZAK5Kmuq8_0n4,8131
|
|
125
|
+
pytcl/mathematical_functions/special_functions/error_functions.py,sha256=6i5HqQfYdcz0UNhLnHpoMCnWzzZypjckSHTC5ISrcHA,6990
|
|
126
|
+
pytcl/mathematical_functions/special_functions/gamma_functions.py,sha256=riTiy1cqYFtJrzscw0vgTkCaPBCPDGN8Ge6qWAD1zBg,11086
|
|
126
127
|
pytcl/mathematical_functions/special_functions/hypergeometric.py,sha256=mCBf5NPl0mOkwvIwAUp-sbXshin5HyGsdqEeGbYt3wQ,11428
|
|
127
|
-
pytcl/mathematical_functions/special_functions/lambert_w.py,sha256=
|
|
128
|
-
pytcl/mathematical_functions/special_functions/marcum_q.py,sha256=
|
|
128
|
+
pytcl/mathematical_functions/special_functions/lambert_w.py,sha256=flLSf_7IY5sRXzd2aGgyXfJTRCjekgtvguBV3MhB9GE,6943
|
|
129
|
+
pytcl/mathematical_functions/special_functions/marcum_q.py,sha256=ASQ2vVfhmx4iEvtZTyiQ60-Hy8Qxl_4XgJzYufayJaQ,9910
|
|
129
130
|
pytcl/mathematical_functions/statistics/__init__.py,sha256=dfypStgmnFmOrnWcm-3CEvLinONHraFgx9O66_37bqw,1278
|
|
130
131
|
pytcl/mathematical_functions/statistics/distributions.py,sha256=icfFIIKCEFzkpFHuYGWL197nm8wvS7UPJlr9kd_uEgw,19373
|
|
131
132
|
pytcl/mathematical_functions/statistics/estimators.py,sha256=TLnYXSwk5MzBakZrzDBupbOB3ONmJI7q1-oB2xuSVQM,10831
|
|
@@ -135,14 +136,14 @@ pytcl/mathematical_functions/transforms/stft.py,sha256=olDzNH02Nta5GoeEdsdX1tTVK
|
|
|
135
136
|
pytcl/mathematical_functions/transforms/wavelets.py,sha256=lR71JX5vX_OXl1g9H89OGiimM_oqfU-WfGYJF3uD2z8,21887
|
|
136
137
|
pytcl/misc/__init__.py,sha256=SCHf_lQVfdl2gwUluHBiIloTF8HRH8EkgYfbNr7zOug,33
|
|
137
138
|
pytcl/navigation/__init__.py,sha256=k1_x_FnnPrIzGeNu7zejPtPubIhweBgCfwqlZJEMw0I,6042
|
|
138
|
-
pytcl/navigation/geodesy.py,sha256=
|
|
139
|
-
pytcl/navigation/great_circle.py,sha256=
|
|
139
|
+
pytcl/navigation/geodesy.py,sha256=NH4Txv_VtUdBk6LkQqnSnPfRnG4WnoGF7zGwB-mIbJA,23140
|
|
140
|
+
pytcl/navigation/great_circle.py,sha256=K7CLS8k1P4uN9jpq4Nzc6jk_bSmo-ppb3vyUJbwYjVg,25503
|
|
140
141
|
pytcl/navigation/ins.py,sha256=OIi8_RjrgEYl0MFpJEFMjIlpgX8DYGTEhdLEvqG-ABU,31151
|
|
141
142
|
pytcl/navigation/ins_gnss.py,sha256=euKF5JGgwmVBsw3jBf7_wa2z1BpZeVbSNmBuwzhGS6c,30157
|
|
142
|
-
pytcl/navigation/rhumb.py,sha256=
|
|
143
|
+
pytcl/navigation/rhumb.py,sha256=lEr3LJqowT-WsdSA4E-V7BFmaqxoI7OpJa05pl_-uGg,20562
|
|
143
144
|
pytcl/performance_evaluation/__init__.py,sha256=tM2pnBfDb2XbnLt4Y5MQ6w6XBwFy_5bf_y0toZmxx88,1859
|
|
144
|
-
pytcl/performance_evaluation/estimation_metrics.py,sha256=
|
|
145
|
-
pytcl/performance_evaluation/track_metrics.py,sha256=
|
|
145
|
+
pytcl/performance_evaluation/estimation_metrics.py,sha256=5dNzgMYTWt0bdGfIWgmc8diWA5SgivLvaSt_OahUhfk,14593
|
|
146
|
+
pytcl/performance_evaluation/track_metrics.py,sha256=4AJyU8mqczKnuOTi3eD8WqC56Xp2xxE-pwupM5WwBsE,14396
|
|
146
147
|
pytcl/physical_values/__init__.py,sha256=SGbg6b0d4dWebE3baW4OlJshL00grG5E4wABw6jxl20,44
|
|
147
148
|
pytcl/plotting/__init__.py,sha256=YtYnKYHL5lN6EaT_bwwR3h89NW0HSMToIWHhHBxcidY,3126
|
|
148
149
|
pytcl/plotting/coordinates.py,sha256=kk1UO5aRPCUt206QS4COgtaExZI1Mjhi4P6falQCQLI,17247
|
|
@@ -152,20 +153,20 @@ pytcl/plotting/tracks.py,sha256=RoQyjpMcPm16mQqj4RvDOzPgD6UpHCOid6hxAN3kGC0,2317
|
|
|
152
153
|
pytcl/scheduling/__init__.py,sha256=jTqMSKcsCrWU_Fh6WaT6BW5WatNHyyEYjFbsv6X18Oc,39
|
|
153
154
|
pytcl/static_estimation/__init__.py,sha256=sSEhqq35jq_MpRLnBtWjKXwGZ9dqIw71iwji-TNwXmc,2222
|
|
154
155
|
pytcl/static_estimation/least_squares.py,sha256=8ouOyRGC7K-W8fynZMWlc2-KAFojvTbuzcqi5uS_sVA,13432
|
|
155
|
-
pytcl/static_estimation/maximum_likelihood.py,sha256=
|
|
156
|
-
pytcl/static_estimation/robust.py,sha256=
|
|
156
|
+
pytcl/static_estimation/maximum_likelihood.py,sha256=82tjFEEecNmTLrOrFKldEpkDrn4xC980qHZTZoOy3UY,23393
|
|
157
|
+
pytcl/static_estimation/robust.py,sha256=E9mmXcL1PycmyWvUnmLUbpErNvIbpu_XNAMGECmcMmU,20091
|
|
157
158
|
pytcl/terrain/__init__.py,sha256=e7plNQI5Y_jpZ24r82AgqdX0ChmmyYoeT7HReclnGXc,3228
|
|
158
|
-
pytcl/terrain/dem.py,sha256=
|
|
159
|
+
pytcl/terrain/dem.py,sha256=3r1qV_FXaQDqEfUYJYSMrNNefd9hXRk8OGFkk3A3k9k,22881
|
|
159
160
|
pytcl/terrain/loaders.py,sha256=3BbeFTaZ0I5bOlRFUcnP2eGQn-JyR2QDaUbIorDWdsg,27220
|
|
160
|
-
pytcl/terrain/visibility.py,sha256=
|
|
161
|
+
pytcl/terrain/visibility.py,sha256=03pGWQGE4LY-DQFdqxPTHS-ZCYS9rJQNyAFnuQKe-3I,24992
|
|
161
162
|
pytcl/trackers/__init__.py,sha256=Gw79xlSIUzdPV8bN1slNWUlGxE3d-NsVmbMygkYVV20,1151
|
|
162
|
-
pytcl/trackers/hypothesis.py,sha256=
|
|
163
|
+
pytcl/trackers/hypothesis.py,sha256=cmcLWdSTbAoapl0EhsYcYBos7RXLzgHBfFVUUUh3Hmo,20210
|
|
163
164
|
pytcl/trackers/mht.py,sha256=osEOXMaCeTt1eVn_E08dLRhEvBroVmf8b81zO5Zp1lU,20720
|
|
164
165
|
pytcl/trackers/multi_target.py,sha256=RDITa0xnbgtVYAMj5XXp4lljo5lZ2zAAc02KZlOjxbQ,10526
|
|
165
166
|
pytcl/trackers/single_target.py,sha256=Yy3FwaNTArMWcaod-0HVeiioNV4xLWxNDn_7ZPVqQYs,6562
|
|
166
167
|
pytcl/transponders/__init__.py,sha256=5fL4u3lKCYgPLo5uFeuZbtRZkJPABntuKYGUvVgMMEI,41
|
|
167
|
-
nrl_tracker-1.9.
|
|
168
|
-
nrl_tracker-1.9.
|
|
169
|
-
nrl_tracker-1.9.
|
|
170
|
-
nrl_tracker-1.9.
|
|
171
|
-
nrl_tracker-1.9.
|
|
168
|
+
nrl_tracker-1.9.2.dist-info/LICENSE,sha256=rB5G4WppIIUzMOYr2N6uyYlNJ00hRJqE5tie6BMvYuE,1612
|
|
169
|
+
nrl_tracker-1.9.2.dist-info/METADATA,sha256=HPSMMmbYsxCQpku97YqiIiaTut7fd0LOxLUBKCoMV-Y,12452
|
|
170
|
+
nrl_tracker-1.9.2.dist-info/WHEEL,sha256=pL8R0wFFS65tNSRnaOVrsw9EOkOqxLrlUPenUYnJKNo,91
|
|
171
|
+
nrl_tracker-1.9.2.dist-info/top_level.txt,sha256=17megxcrTPBWwPZTh6jTkwTKxX7No-ZqRpyvElnnO-s,6
|
|
172
|
+
nrl_tracker-1.9.2.dist-info/RECORD,,
|
pytcl/__init__.py
CHANGED
|
@@ -6,7 +6,7 @@ systems, dynamic models, estimation algorithms, and mathematical functions.
|
|
|
6
6
|
|
|
7
7
|
This is a Python port of the U.S. Naval Research Laboratory's Tracker Component
|
|
8
8
|
Library originally written in MATLAB.
|
|
9
|
-
**Current Version:** 1.9.
|
|
9
|
+
**Current Version:** 1.9.2 (January 4, 2026)
|
|
10
10
|
**Status:** Production-ready, 2,133 tests passing, 76% line coverage
|
|
11
11
|
Examples
|
|
12
12
|
--------
|
|
@@ -21,7 +21,7 @@ References
|
|
|
21
21
|
no. 5, pp. 18-27, May 2017.
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
__version__ = "1.9.
|
|
24
|
+
__version__ = "1.9.2"
|
|
25
25
|
__author__ = "Python Port Contributors"
|
|
26
26
|
__original_author__ = "David F. Crouse, Naval Research Laboratory"
|
|
27
27
|
|
|
@@ -322,6 +322,24 @@ def compute_gate_volume(
|
|
|
322
322
|
V = c_m * sqrt(det(S)) * gamma^(m/2)
|
|
323
323
|
|
|
324
324
|
where c_m is the volume of the unit hypersphere in m dimensions.
|
|
325
|
+
|
|
326
|
+
Examples
|
|
327
|
+
--------
|
|
328
|
+
Compute gate volume for a 2D measurement with 99% gate probability:
|
|
329
|
+
|
|
330
|
+
>>> import numpy as np
|
|
331
|
+
>>> from scipy.stats import chi2
|
|
332
|
+
>>> S = np.array([[4.0, 0.0], [0.0, 1.0]]) # innovation covariance
|
|
333
|
+
>>> gate_prob = 0.99
|
|
334
|
+
>>> threshold = chi2.ppf(gate_prob, df=2)
|
|
335
|
+
>>> volume = compute_gate_volume(S, threshold)
|
|
336
|
+
>>> volume > 0
|
|
337
|
+
True
|
|
338
|
+
|
|
339
|
+
See Also
|
|
340
|
+
--------
|
|
341
|
+
ellipsoidal_gate : Test if measurement passes gate.
|
|
342
|
+
mahalanobis_distance : Compute distance used in gating.
|
|
325
343
|
"""
|
|
326
344
|
S = np.asarray(innovation_covariance, dtype=np.float64)
|
|
327
345
|
m = S.shape[0]
|
|
@@ -136,6 +136,22 @@ def compute_likelihood_matrix(
|
|
|
136
136
|
Likelihood values, shape (n_tracks, n_meas).
|
|
137
137
|
gated : ndarray[Any]
|
|
138
138
|
Boolean gating matrix, shape (n_tracks, n_meas).
|
|
139
|
+
|
|
140
|
+
Examples
|
|
141
|
+
--------
|
|
142
|
+
>>> import numpy as np
|
|
143
|
+
>>> # Two tracks, two measurements
|
|
144
|
+
>>> states = [np.array([0.0, 1.0]), np.array([5.0, 0.0])]
|
|
145
|
+
>>> covs = [np.eye(2) * 0.5, np.eye(2) * 0.5]
|
|
146
|
+
>>> measurements = np.array([[0.1], [5.2]])
|
|
147
|
+
>>> H = np.array([[1, 0]])
|
|
148
|
+
>>> R = np.array([[0.1]])
|
|
149
|
+
>>> L, gated = compute_likelihood_matrix(states, covs, measurements, H, R)
|
|
150
|
+
>>> L.shape
|
|
151
|
+
(2, 2)
|
|
152
|
+
>>> # Track 0 should have high likelihood for measurement 0
|
|
153
|
+
>>> L[0, 0] > L[0, 1]
|
|
154
|
+
True
|
|
139
155
|
"""
|
|
140
156
|
n_tracks = len(track_states)
|
|
141
157
|
n_meas = len(measurements)
|
|
@@ -191,6 +207,23 @@ def jpda_probabilities(
|
|
|
191
207
|
Association probability matrix, shape (n_tracks, n_meas + 1).
|
|
192
208
|
beta[i, j] = P(measurement j is from track i) for j < n_meas.
|
|
193
209
|
beta[i, n_meas] = P(track i has no measurement).
|
|
210
|
+
|
|
211
|
+
Examples
|
|
212
|
+
--------
|
|
213
|
+
>>> import numpy as np
|
|
214
|
+
>>> # Likelihood matrix: 2 tracks, 2 measurements
|
|
215
|
+
>>> # Track 0 has high likelihood for meas 0
|
|
216
|
+
>>> # Track 1 has high likelihood for meas 1
|
|
217
|
+
>>> likelihood = np.array([[0.9, 0.1],
|
|
218
|
+
... [0.1, 0.8]])
|
|
219
|
+
>>> gated = np.array([[True, True],
|
|
220
|
+
... [True, True]])
|
|
221
|
+
>>> beta = jpda_probabilities(likelihood, gated, detection_prob=0.9)
|
|
222
|
+
>>> beta.shape # 2 tracks, 3 columns (2 meas + 1 miss)
|
|
223
|
+
(2, 3)
|
|
224
|
+
>>> # Track 0 most likely associated with measurement 0
|
|
225
|
+
>>> np.argmax(beta[0, :2])
|
|
226
|
+
0
|
|
194
227
|
"""
|
|
195
228
|
n_tracks, n_meas = likelihood_matrix.shape
|
|
196
229
|
|
|
@@ -591,6 +624,29 @@ def jpda(
|
|
|
591
624
|
-------
|
|
592
625
|
result : JPDAResult
|
|
593
626
|
Association probabilities and related information.
|
|
627
|
+
|
|
628
|
+
Examples
|
|
629
|
+
--------
|
|
630
|
+
Compute association probabilities for 2 tracks and 3 measurements:
|
|
631
|
+
|
|
632
|
+
>>> import numpy as np
|
|
633
|
+
>>> # Two tracks with [x, vx] state
|
|
634
|
+
>>> states = [np.array([0.0, 1.0]), np.array([10.0, -0.5])]
|
|
635
|
+
>>> covariances = [np.eye(2) * 0.5, np.eye(2) * 0.5]
|
|
636
|
+
>>> # Three position measurements
|
|
637
|
+
>>> measurements = np.array([[0.1], [9.8], [5.0]])
|
|
638
|
+
>>> H = np.array([[1, 0]]) # measure position only
|
|
639
|
+
>>> R = np.array([[0.1]])
|
|
640
|
+
>>> result = jpda(states, covariances, measurements, H, R)
|
|
641
|
+
>>> result.association_probs.shape # (2 tracks, 4 columns: 3 meas + miss)
|
|
642
|
+
(2, 4)
|
|
643
|
+
>>> # Track 0 should have high prob for measurement 0
|
|
644
|
+
>>> result.association_probs[0, 0] > 0.5
|
|
645
|
+
True
|
|
646
|
+
|
|
647
|
+
See Also
|
|
648
|
+
--------
|
|
649
|
+
jpda_update : JPDA with state update.
|
|
594
650
|
"""
|
|
595
651
|
# Convert inputs
|
|
596
652
|
track_states = [np.asarray(x, dtype=np.float64).flatten() for x in track_states]
|
|
@@ -67,6 +67,20 @@ def validate_cost_tensor(cost_tensor: NDArray[np.float64]) -> Tuple[int, ...]:
|
|
|
67
67
|
------
|
|
68
68
|
ValueError
|
|
69
69
|
If tensor has fewer than 2 dimensions.
|
|
70
|
+
|
|
71
|
+
Examples
|
|
72
|
+
--------
|
|
73
|
+
>>> import numpy as np
|
|
74
|
+
>>> cost = np.random.rand(3, 4, 5)
|
|
75
|
+
>>> dims = validate_cost_tensor(cost)
|
|
76
|
+
>>> dims
|
|
77
|
+
(3, 4, 5)
|
|
78
|
+
>>> # 1D tensor should raise error
|
|
79
|
+
>>> try:
|
|
80
|
+
... validate_cost_tensor(np.array([1, 2, 3]))
|
|
81
|
+
... except ValueError:
|
|
82
|
+
... print("Caught expected error")
|
|
83
|
+
Caught expected error
|
|
70
84
|
"""
|
|
71
85
|
if cost_tensor.ndim < 2:
|
|
72
86
|
raise ValueError(
|
|
@@ -98,6 +112,21 @@ def greedy_assignment_nd(
|
|
|
98
112
|
AssignmentNDResult
|
|
99
113
|
Assignments, total cost, and algorithm info.
|
|
100
114
|
|
|
115
|
+
Examples
|
|
116
|
+
--------
|
|
117
|
+
>>> import numpy as np
|
|
118
|
+
>>> # 3D cost tensor: 3 measurements x 2 tracks x 2 hypotheses
|
|
119
|
+
>>> cost = np.array([
|
|
120
|
+
... [[1.0, 5.0], [3.0, 2.0]], # meas 0
|
|
121
|
+
... [[4.0, 1.0], [2.0, 6.0]], # meas 1
|
|
122
|
+
... [[2.0, 3.0], [5.0, 1.0]], # meas 2
|
|
123
|
+
... ])
|
|
124
|
+
>>> result = greedy_assignment_nd(cost)
|
|
125
|
+
>>> result.cost # Total cost of greedy solution
|
|
126
|
+
4.0
|
|
127
|
+
>>> len(result.assignments) # Number of assignments made
|
|
128
|
+
2
|
|
129
|
+
|
|
101
130
|
Notes
|
|
102
131
|
-----
|
|
103
132
|
Greedy assignment is fast O(n log n) but not optimal. Used as
|
|
@@ -178,6 +207,18 @@ def relaxation_assignment_nd(
|
|
|
178
207
|
AssignmentNDResult
|
|
179
208
|
Assignments, total cost, convergence info, and optimality gap.
|
|
180
209
|
|
|
210
|
+
Examples
|
|
211
|
+
--------
|
|
212
|
+
>>> import numpy as np
|
|
213
|
+
>>> # 3x3x3 assignment problem
|
|
214
|
+
>>> np.random.seed(42)
|
|
215
|
+
>>> cost = np.random.rand(3, 3, 3)
|
|
216
|
+
>>> result = relaxation_assignment_nd(cost, max_iterations=50)
|
|
217
|
+
>>> result.converged
|
|
218
|
+
True
|
|
219
|
+
>>> result.assignments.shape[1] # 3D assignments
|
|
220
|
+
3
|
|
221
|
+
|
|
181
222
|
Notes
|
|
182
223
|
-----
|
|
183
224
|
The relaxation approach:
|
|
@@ -297,6 +338,18 @@ def auction_assignment_nd(
|
|
|
297
338
|
AssignmentNDResult
|
|
298
339
|
Assignments, total cost, convergence info, gap estimate.
|
|
299
340
|
|
|
341
|
+
Examples
|
|
342
|
+
--------
|
|
343
|
+
>>> import numpy as np
|
|
344
|
+
>>> # 4D assignment: sensors x measurements x tracks x hypotheses
|
|
345
|
+
>>> np.random.seed(123)
|
|
346
|
+
>>> cost = np.random.rand(2, 3, 3, 2) * 10
|
|
347
|
+
>>> result = auction_assignment_nd(cost, max_iterations=50, epsilon=0.1)
|
|
348
|
+
>>> len(result.assignments) > 0
|
|
349
|
+
True
|
|
350
|
+
>>> result.n_iterations <= 50
|
|
351
|
+
True
|
|
352
|
+
|
|
300
353
|
Notes
|
|
301
354
|
-----
|
|
302
355
|
The algorithm maintains a "price" for each index and allows bidding
|
|
@@ -368,6 +421,18 @@ def detect_dimension_conflicts(
|
|
|
368
421
|
-------
|
|
369
422
|
has_conflicts : bool
|
|
370
423
|
True if any index appears more than once in any dimension.
|
|
424
|
+
|
|
425
|
+
Examples
|
|
426
|
+
--------
|
|
427
|
+
>>> import numpy as np
|
|
428
|
+
>>> # Valid assignment: no index repeated in any dimension
|
|
429
|
+
>>> assignments = np.array([[0, 0], [1, 1]])
|
|
430
|
+
>>> detect_dimension_conflicts(assignments, (3, 3))
|
|
431
|
+
False
|
|
432
|
+
>>> # Invalid: index 0 used twice in first dimension
|
|
433
|
+
>>> assignments = np.array([[0, 0], [0, 1]])
|
|
434
|
+
>>> detect_dimension_conflicts(assignments, (3, 3))
|
|
435
|
+
True
|
|
371
436
|
"""
|
|
372
437
|
n_dims = len(dims)
|
|
373
438
|
|
|
@@ -104,6 +104,20 @@ def assignment_to_flow_network(
|
|
|
104
104
|
Positive = supply, negative = demand.
|
|
105
105
|
node_names : ndarray
|
|
106
106
|
Names of nodes for reference.
|
|
107
|
+
|
|
108
|
+
Examples
|
|
109
|
+
--------
|
|
110
|
+
>>> import numpy as np
|
|
111
|
+
>>> # 2 workers, 3 tasks
|
|
112
|
+
>>> cost = np.array([[1.0, 2.0, 3.0],
|
|
113
|
+
... [4.0, 5.0, 6.0]])
|
|
114
|
+
>>> edges, supplies, names = assignment_to_flow_network(cost)
|
|
115
|
+
>>> len(edges) # source->workers + workers->tasks + tasks->sink
|
|
116
|
+
11
|
|
117
|
+
>>> supplies[0] # source supplies 2 (num workers)
|
|
118
|
+
2.0
|
|
119
|
+
>>> names[0]
|
|
120
|
+
'source'
|
|
107
121
|
"""
|
|
108
122
|
m, n = cost_matrix.shape
|
|
109
123
|
|
|
@@ -187,6 +201,20 @@ def min_cost_flow_successive_shortest_paths(
|
|
|
187
201
|
MinCostFlowResult
|
|
188
202
|
Solution with flow values, cost, status, and iterations.
|
|
189
203
|
|
|
204
|
+
Examples
|
|
205
|
+
--------
|
|
206
|
+
>>> import numpy as np
|
|
207
|
+
>>> from pytcl.assignment_algorithms.network_flow import (
|
|
208
|
+
... FlowEdge, assignment_to_flow_network
|
|
209
|
+
... )
|
|
210
|
+
>>> cost = np.array([[1.0, 5.0], [4.0, 2.0]])
|
|
211
|
+
>>> edges, supplies, _ = assignment_to_flow_network(cost)
|
|
212
|
+
>>> result = min_cost_flow_successive_shortest_paths(edges, supplies)
|
|
213
|
+
>>> result.status == FlowStatus.OPTIMAL
|
|
214
|
+
True
|
|
215
|
+
>>> result.cost # Optimal is 1+2=3 (diagonal)
|
|
216
|
+
3.0
|
|
217
|
+
|
|
190
218
|
Notes
|
|
191
219
|
-----
|
|
192
220
|
This is a simplified implementation using Bellman-Ford for shortest
|
|
@@ -445,6 +473,18 @@ def min_cost_assignment_via_flow(
|
|
|
445
473
|
total_cost : float
|
|
446
474
|
Total assignment cost.
|
|
447
475
|
|
|
476
|
+
Examples
|
|
477
|
+
--------
|
|
478
|
+
>>> import numpy as np
|
|
479
|
+
>>> cost = np.array([[1.0, 5.0, 9.0],
|
|
480
|
+
... [3.0, 2.0, 8.0],
|
|
481
|
+
... [7.0, 6.0, 4.0]])
|
|
482
|
+
>>> assignment, total_cost = min_cost_assignment_via_flow(cost)
|
|
483
|
+
>>> total_cost # Optimal assignment: (0,0), (1,1), (2,2) = 1+2+4 = 7
|
|
484
|
+
7.0
|
|
485
|
+
>>> len(assignment)
|
|
486
|
+
3
|
|
487
|
+
|
|
448
488
|
Notes
|
|
449
489
|
-----
|
|
450
490
|
Phase 1B: Dijkstra-based optimization provides O(K*E log V) vs
|
|
@@ -446,6 +446,12 @@ def sun_position(
|
|
|
446
446
|
velocity : ndarray, shape (3,)
|
|
447
447
|
Sun velocity in AU/day
|
|
448
448
|
|
|
449
|
+
Examples
|
|
450
|
+
--------
|
|
451
|
+
>>> r, v = sun_position(2451545.0) # J2000.0 # doctest: +SKIP
|
|
452
|
+
>>> np.linalg.norm(r) # Distance from SSB # doctest: +SKIP
|
|
453
|
+
0.00...
|
|
454
|
+
|
|
449
455
|
See Also
|
|
450
456
|
--------
|
|
451
457
|
DEEphemeris.sun_position : Full ephemeris class with caching
|
|
@@ -473,6 +479,12 @@ def moon_position(
|
|
|
473
479
|
velocity : ndarray, shape (3,)
|
|
474
480
|
Moon velocity in AU/day
|
|
475
481
|
|
|
482
|
+
Examples
|
|
483
|
+
--------
|
|
484
|
+
>>> r, v = moon_position(2451545.0, 'earth_centered') # doctest: +SKIP
|
|
485
|
+
>>> np.linalg.norm(r) * 149597870.7 # Distance in km # doctest: +SKIP
|
|
486
|
+
402...
|
|
487
|
+
|
|
476
488
|
See Also
|
|
477
489
|
--------
|
|
478
490
|
DEEphemeris.moon_position : Full ephemeris class with caching
|
|
@@ -533,5 +545,11 @@ def barycenter_position(
|
|
|
533
545
|
velocity : ndarray, shape (3,)
|
|
534
546
|
Velocity in AU/day
|
|
535
547
|
|
|
548
|
+
Examples
|
|
549
|
+
--------
|
|
550
|
+
>>> r, v = barycenter_position('mars', 2451545.0) # doctest: +SKIP
|
|
551
|
+
>>> np.linalg.norm(r) # Mars distance from SSB # doctest: +SKIP
|
|
552
|
+
1.4...
|
|
553
|
+
|
|
536
554
|
"""
|
|
537
555
|
return _get_default_ephemeris().barycenter_position(body, jd)
|