nrl-tracker 1.9.1__tar.gz → 1.9.2__tar.gz
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.1/nrl_tracker.egg-info → nrl_tracker-1.9.2}/PKG-INFO +4 -4
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/README.md +3 -3
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2/nrl_tracker.egg-info}/PKG-INFO +4 -4
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/nrl_tracker.egg-info/SOURCES.txt +1 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pyproject.toml +1 -1
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/__init__.py +2 -2
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/gating.py +18 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/jpda.py +56 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/nd_assignment.py +65 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/network_flow.py +40 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/ephemerides.py +18 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/orbital_mechanics.py +131 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/atmosphere/ionosphere.py +44 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/atmosphere/models.py +29 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/clustering/dbscan.py +9 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/clustering/gaussian_mixture.py +20 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/clustering/hierarchical.py +29 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/clustering/kmeans.py +9 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/conversions/geodetic.py +46 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/conversions/spherical.py +35 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/rotations/rotations.py +147 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/core/__init__.py +16 -0
- nrl_tracker-1.9.2/pytcl/core/maturity.py +346 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/gaussian_sum_filter.py +55 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/imm.py +29 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/information_filter.py +64 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/extended.py +56 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/linear.py +69 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/unscented.py +81 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/particle_filters/bootstrap.py +146 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/rbpf.py +51 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/smoothers.py +58 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/continuous_time/dynamics.py +104 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/discrete_time/coordinated_turn.py +6 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/discrete_time/singer.py +12 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/process_noise/coordinated_turn.py +46 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/process_noise/polynomial.py +6 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/process_noise/singer.py +52 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/gravity/clenshaw.py +60 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/gravity/egm.py +47 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/gravity/models.py +34 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/gravity/spherical_harmonics.py +73 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/gravity/tides.py +34 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/numerical_integration/quadrature.py +85 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/special_functions/bessel.py +55 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/special_functions/elliptic.py +42 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/special_functions/error_functions.py +49 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/special_functions/gamma_functions.py +43 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/special_functions/lambert_w.py +5 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/special_functions/marcum_q.py +16 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/navigation/geodesy.py +101 -2
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/navigation/great_circle.py +71 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/navigation/rhumb.py +74 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/performance_evaluation/estimation_metrics.py +70 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/performance_evaluation/track_metrics.py +30 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/static_estimation/maximum_likelihood.py +54 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/static_estimation/robust.py +57 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/terrain/dem.py +69 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/terrain/visibility.py +65 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/trackers/hypothesis.py +65 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/CONTRIBUTING.md +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/LICENSE +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/MANIFEST.in +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/nrl_tracker.egg-info/dependency_links.txt +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/nrl_tracker.egg-info/requires.txt +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/nrl_tracker.egg-info/top_level.txt +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/data_association.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/dijkstra_min_cost.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/network_simplex.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/three_dimensional/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/three_dimensional/assignment.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/two_dimensional/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/two_dimensional/assignment.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/assignment_algorithms/two_dimensional/kbest.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/lambert.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/reference_frames.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/relativity.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/sgp4.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/special_orbits.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/time_systems.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/astronomical/tle.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/atmosphere/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/atmosphere/nrlmsise00.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/clustering/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/containers/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/containers/base.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/containers/cluster_set.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/containers/covertree.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/containers/kd_tree.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/containers/measurement_set.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/containers/rtree.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/containers/track_list.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/containers/vptree.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/conversions/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/jacobians/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/jacobians/jacobians.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/projections/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/projections/projections.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/coordinate_systems/rotations/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/core/array_utils.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/core/constants.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/core/exceptions.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/core/optional_deps.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/core/validation.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/batch_estimation/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/constrained.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/h_infinity.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/matrix_utils.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/square_root.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/sr_ukf.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/types.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/kalman/ud_filter.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/measurement_update/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_estimation/particle_filters/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/continuous_time/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/discrete_time/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/discrete_time/polynomial.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/dynamic_models/process_noise/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/gravity/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/logging_config.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/magnetism/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/magnetism/emm.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/magnetism/igrf.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/magnetism/wmm.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/basic_matrix/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/basic_matrix/decompositions.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/basic_matrix/special_matrices.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/combinatorics/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/combinatorics/combinatorics.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/continuous_optimization/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/geometry/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/geometry/geometry.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/interpolation/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/interpolation/interpolation.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/numerical_integration/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/polynomials/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/signal_processing/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/signal_processing/detection.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/signal_processing/filters.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/signal_processing/matched_filter.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/special_functions/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/special_functions/debye.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/special_functions/hypergeometric.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/statistics/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/statistics/distributions.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/statistics/estimators.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/transforms/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/transforms/fourier.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/transforms/stft.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/mathematical_functions/transforms/wavelets.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/misc/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/navigation/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/navigation/ins.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/navigation/ins_gnss.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/performance_evaluation/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/physical_values/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/plotting/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/plotting/coordinates.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/plotting/ellipses.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/plotting/metrics.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/plotting/tracks.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/scheduling/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/static_estimation/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/static_estimation/least_squares.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/terrain/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/terrain/loaders.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/trackers/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/trackers/mht.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/trackers/multi_target.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/trackers/single_target.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/pytcl/transponders/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/setup.cfg +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/__init__.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/conftest.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_additional_trees.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_assignment_algorithms.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_astronomical.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_clustering.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_constrained_ekf.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_coordinate_systems.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_coverage_boost.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_coverage_boost_2.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_dynamic_models.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_egm.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_emm.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_ephemerides.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_exceptions.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_gaussian_mixtures.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_gaussian_sum_filter.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_geophysical.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_great_circle.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_h_infinity.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_ins.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_ins_gnss.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_jpda.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_kalman_filters.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_mathematical_functions.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_maximum_likelihood.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_mht.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_nd_assignment.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_network_flow.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_nrlmsise00.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_optional_deps.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_performance_evaluation.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_phase6_specialized.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_plotting.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_projections.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_rbpf.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_relativity.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_rhumb.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_sgp4.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_signal_processing.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_smoothers.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_spatial_containers_parametrized.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_spatial_structures.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_special_functions.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_special_orbits.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_static_estimation.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_terrain.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_terrain_loaders.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_tides.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_tod_mod.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_trackers.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_tracking_containers.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_transforms.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/test_validation.py +0 -0
- {nrl_tracker-1.9.1 → nrl_tracker-1.9.2}/tests/unit/test_core.py +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: nrl-tracker[astronomy,dev,geodesy,optimization,signal,visualizati
|
|
|
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,16 +1,16 @@
|
|
|
1
1
|
# Tracker Component Library (Python)
|
|
2
2
|
|
|
3
|
-
[](https://pypi.org/project/nrl-tracker/)
|
|
4
4
|
[](https://www.python.org/downloads/)
|
|
5
5
|
[](https://en.wikipedia.org/wiki/Public_domain)
|
|
6
6
|
[](https://github.com/psf/black)
|
|
7
|
-
[](https://github.com/nedonatelli/TCL)
|
|
8
8
|
[](docs/gap_analysis.rst)
|
|
9
9
|
[](mypy.ini)
|
|
10
10
|
|
|
11
11
|
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.
|
|
12
12
|
|
|
13
|
-
**1,070+ functions** | **153 modules** | **
|
|
13
|
+
**1,070+ functions** | **153 modules** | **2,133 tests** | **100% MATLAB parity**
|
|
14
14
|
|
|
15
15
|
## Overview
|
|
16
16
|
|
|
@@ -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: nrl-tracker[astronomy,dev,geodesy,optimization,signal,visualizati
|
|
|
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
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nrl-tracker"
|
|
7
|
-
version = "1.9.
|
|
7
|
+
version = "1.9.2"
|
|
8
8
|
description = "Python port of the U.S. Naval Research Laboratory's Tracker Component Library for target tracking algorithms"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -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)
|
|
@@ -157,6 +157,12 @@ def mean_to_hyperbolic_anomaly(
|
|
|
157
157
|
-------
|
|
158
158
|
H : float
|
|
159
159
|
Hyperbolic anomaly (radians).
|
|
160
|
+
|
|
161
|
+
Examples
|
|
162
|
+
--------
|
|
163
|
+
>>> H = mean_to_hyperbolic_anomaly(1.0, 1.5)
|
|
164
|
+
>>> abs(1.5 * np.sinh(H) - H - 1.0) < 1e-10
|
|
165
|
+
True
|
|
160
166
|
"""
|
|
161
167
|
if e <= 1:
|
|
162
168
|
raise ValueError(f"Eccentricity must be > 1 for hyperbolic orbits, got {e}")
|
|
@@ -196,6 +202,12 @@ def eccentric_to_true_anomaly(E: float, e: float) -> float:
|
|
|
196
202
|
-------
|
|
197
203
|
nu : float
|
|
198
204
|
True anomaly (radians), in [0, 2*pi).
|
|
205
|
+
|
|
206
|
+
Examples
|
|
207
|
+
--------
|
|
208
|
+
>>> nu = eccentric_to_true_anomaly(np.pi/4, 0.5)
|
|
209
|
+
>>> 0 <= nu < 2 * np.pi
|
|
210
|
+
True
|
|
199
211
|
"""
|
|
200
212
|
# Use half-angle formula for numerical stability
|
|
201
213
|
nu = 2 * np.arctan2(np.sqrt(1 + e) * np.sin(E / 2), np.sqrt(1 - e) * np.cos(E / 2))
|
|
@@ -217,6 +229,12 @@ def true_to_eccentric_anomaly(nu: float, e: float) -> float:
|
|
|
217
229
|
-------
|
|
218
230
|
E : float
|
|
219
231
|
Eccentric anomaly (radians), in [0, 2*pi).
|
|
232
|
+
|
|
233
|
+
Examples
|
|
234
|
+
--------
|
|
235
|
+
>>> E = true_to_eccentric_anomaly(np.pi/3, 0.5)
|
|
236
|
+
>>> 0 <= E < 2 * np.pi
|
|
237
|
+
True
|
|
220
238
|
"""
|
|
221
239
|
E = 2 * np.arctan2(np.sqrt(1 - e) * np.sin(nu / 2), np.sqrt(1 + e) * np.cos(nu / 2))
|
|
222
240
|
return E % (2 * np.pi)
|
|
@@ -237,6 +255,12 @@ def hyperbolic_to_true_anomaly(H: float, e: float) -> float:
|
|
|
237
255
|
-------
|
|
238
256
|
nu : float
|
|
239
257
|
True anomaly (radians).
|
|
258
|
+
|
|
259
|
+
Examples
|
|
260
|
+
--------
|
|
261
|
+
>>> nu = hyperbolic_to_true_anomaly(0.5, 1.5)
|
|
262
|
+
>>> isinstance(nu, float)
|
|
263
|
+
True
|
|
240
264
|
"""
|
|
241
265
|
nu = 2 * np.arctan(np.sqrt((e + 1) / (e - 1)) * np.tanh(H / 2))
|
|
242
266
|
return nu
|
|
@@ -277,6 +301,12 @@ def eccentric_to_mean_anomaly(E: float, e: float) -> float:
|
|
|
277
301
|
-------
|
|
278
302
|
M : float
|
|
279
303
|
Mean anomaly (radians).
|
|
304
|
+
|
|
305
|
+
Examples
|
|
306
|
+
--------
|
|
307
|
+
>>> M = eccentric_to_mean_anomaly(np.pi/4, 0.5)
|
|
308
|
+
>>> 0 <= M < 2 * np.pi
|
|
309
|
+
True
|
|
280
310
|
"""
|
|
281
311
|
M = E - e * np.sin(E)
|
|
282
312
|
return M % (2 * np.pi)
|
|
@@ -297,6 +327,12 @@ def mean_to_true_anomaly(M: float, e: float) -> float:
|
|
|
297
327
|
-------
|
|
298
328
|
nu : float
|
|
299
329
|
True anomaly (radians).
|
|
330
|
+
|
|
331
|
+
Examples
|
|
332
|
+
--------
|
|
333
|
+
>>> nu = mean_to_true_anomaly(np.pi/4, 0.1)
|
|
334
|
+
>>> 0 <= nu < 2 * np.pi
|
|
335
|
+
True
|
|
300
336
|
"""
|
|
301
337
|
if e < 1:
|
|
302
338
|
E = mean_to_eccentric_anomaly(M, e)
|
|
@@ -514,6 +550,12 @@ def orbital_period(a: float, mu: float = GM_EARTH) -> float:
|
|
|
514
550
|
-------
|
|
515
551
|
T : float
|
|
516
552
|
Orbital period (seconds).
|
|
553
|
+
|
|
554
|
+
Examples
|
|
555
|
+
--------
|
|
556
|
+
>>> T = orbital_period(7000) # LEO satellite
|
|
557
|
+
>>> T / 60 # Convert to minutes # doctest: +SKIP
|
|
558
|
+
97.8...
|
|
517
559
|
"""
|
|
518
560
|
if a <= 0:
|
|
519
561
|
raise ValueError("Semi-major axis must be positive for elliptic orbits")
|
|
@@ -535,6 +577,13 @@ def mean_motion(a: float, mu: float = GM_EARTH) -> float:
|
|
|
535
577
|
-------
|
|
536
578
|
n : float
|
|
537
579
|
Mean motion (radians/second).
|
|
580
|
+
|
|
581
|
+
Examples
|
|
582
|
+
--------
|
|
583
|
+
>>> n = mean_motion(42164) # GEO orbit
|
|
584
|
+
>>> revs_per_day = n * 86400 / (2 * np.pi)
|
|
585
|
+
>>> abs(revs_per_day - 1.0) < 0.01 # Approximately 1 rev/day
|
|
586
|
+
True
|
|
538
587
|
"""
|
|
539
588
|
return np.sqrt(mu / abs(a) ** 3)
|
|
540
589
|
|
|
@@ -607,6 +656,15 @@ def kepler_propagate_state(
|
|
|
607
656
|
-------
|
|
608
657
|
new_state : StateVector
|
|
609
658
|
Propagated state vector.
|
|
659
|
+
|
|
660
|
+
Examples
|
|
661
|
+
--------
|
|
662
|
+
>>> r = np.array([7000.0, 0.0, 0.0])
|
|
663
|
+
>>> v = np.array([0.0, 7.5, 0.0])
|
|
664
|
+
>>> state = StateVector(r=r, v=v)
|
|
665
|
+
>>> new_state = kepler_propagate_state(state, 3600)
|
|
666
|
+
>>> np.linalg.norm(new_state.r) > 0
|
|
667
|
+
True
|
|
610
668
|
"""
|
|
611
669
|
elements = state_to_orbital_elements(state, mu)
|
|
612
670
|
new_elements = kepler_propagate(elements, dt, mu)
|
|
@@ -630,6 +688,12 @@ def vis_viva(r: float, a: float, mu: float = GM_EARTH) -> float:
|
|
|
630
688
|
-------
|
|
631
689
|
v : float
|
|
632
690
|
Orbital velocity (km/s).
|
|
691
|
+
|
|
692
|
+
Examples
|
|
693
|
+
--------
|
|
694
|
+
>>> v = vis_viva(7000, 7000) # Circular orbit
|
|
695
|
+
>>> abs(v - circular_velocity(7000)) < 0.01
|
|
696
|
+
True
|
|
633
697
|
"""
|
|
634
698
|
return np.sqrt(mu * (2 / r - 1 / a))
|
|
635
699
|
|
|
@@ -649,6 +713,15 @@ def specific_angular_momentum(
|
|
|
649
713
|
-------
|
|
650
714
|
h : ndarray
|
|
651
715
|
Specific angular momentum vector (km^2/s).
|
|
716
|
+
|
|
717
|
+
Examples
|
|
718
|
+
--------
|
|
719
|
+
>>> r = np.array([7000.0, 0.0, 0.0])
|
|
720
|
+
>>> v = np.array([0.0, 7.5, 0.0])
|
|
721
|
+
>>> state = StateVector(r=r, v=v)
|
|
722
|
+
>>> h = specific_angular_momentum(state)
|
|
723
|
+
>>> h[2] # Angular momentum in z-direction
|
|
724
|
+
52500.0
|
|
652
725
|
"""
|
|
653
726
|
return np.cross(state.r, state.v)
|
|
654
727
|
|
|
@@ -672,6 +745,15 @@ def specific_orbital_energy(
|
|
|
672
745
|
energy : float
|
|
673
746
|
Specific orbital energy (km^2/s^2).
|
|
674
747
|
Negative for bound orbits, positive for escape trajectories.
|
|
748
|
+
|
|
749
|
+
Examples
|
|
750
|
+
--------
|
|
751
|
+
>>> r = np.array([7000.0, 0.0, 0.0])
|
|
752
|
+
>>> v = np.array([0.0, 7.5, 0.0])
|
|
753
|
+
>>> state = StateVector(r=r, v=v)
|
|
754
|
+
>>> energy = specific_orbital_energy(state)
|
|
755
|
+
>>> energy < 0 # Bound orbit
|
|
756
|
+
True
|
|
675
757
|
"""
|
|
676
758
|
r_mag = np.linalg.norm(state.r)
|
|
677
759
|
v_mag = np.linalg.norm(state.v)
|
|
@@ -692,6 +774,15 @@ def flight_path_angle(state: StateVector) -> float:
|
|
|
692
774
|
gamma : float
|
|
693
775
|
Flight path angle (radians).
|
|
694
776
|
Positive when climbing, negative when descending.
|
|
777
|
+
|
|
778
|
+
Examples
|
|
779
|
+
--------
|
|
780
|
+
>>> r = np.array([7000.0, 0.0, 0.0])
|
|
781
|
+
>>> v = np.array([0.0, 7.5, 0.0]) # Tangential velocity
|
|
782
|
+
>>> state = StateVector(r=r, v=v)
|
|
783
|
+
>>> gamma = flight_path_angle(state)
|
|
784
|
+
>>> abs(gamma) < 0.01 # Nearly zero for circular motion
|
|
785
|
+
True
|
|
695
786
|
"""
|
|
696
787
|
r = np.asarray(state.r)
|
|
697
788
|
v = np.asarray(state.v)
|
|
@@ -720,6 +811,12 @@ def periapsis_radius(a: float, e: float) -> float:
|
|
|
720
811
|
-------
|
|
721
812
|
r_p : float
|
|
722
813
|
Periapsis radius (km).
|
|
814
|
+
|
|
815
|
+
Examples
|
|
816
|
+
--------
|
|
817
|
+
>>> r_p = periapsis_radius(10000, 0.3)
|
|
818
|
+
>>> r_p
|
|
819
|
+
7000.0
|
|
723
820
|
"""
|
|
724
821
|
return a * (1 - e)
|
|
725
822
|
|
|
@@ -739,6 +836,12 @@ def apoapsis_radius(a: float, e: float) -> float:
|
|
|
739
836
|
-------
|
|
740
837
|
r_a : float
|
|
741
838
|
Apoapsis radius (km). Infinite for parabolic/hyperbolic orbits.
|
|
839
|
+
|
|
840
|
+
Examples
|
|
841
|
+
--------
|
|
842
|
+
>>> r_a = apoapsis_radius(10000, 0.3)
|
|
843
|
+
>>> r_a
|
|
844
|
+
13000.0
|
|
742
845
|
"""
|
|
743
846
|
if e >= 1:
|
|
744
847
|
return np.inf
|
|
@@ -769,6 +872,13 @@ def time_since_periapsis(
|
|
|
769
872
|
-------
|
|
770
873
|
t : float
|
|
771
874
|
Time since periapsis (seconds).
|
|
875
|
+
|
|
876
|
+
Examples
|
|
877
|
+
--------
|
|
878
|
+
>>> t = time_since_periapsis(np.pi, 7000, 0.1) # At apoapsis
|
|
879
|
+
>>> T = orbital_period(7000)
|
|
880
|
+
>>> abs(t - T/2) < 1 # Approximately half the period
|
|
881
|
+
True
|
|
772
882
|
"""
|
|
773
883
|
M = true_to_mean_anomaly(nu, e)
|
|
774
884
|
n = mean_motion(a, mu)
|
|
@@ -792,6 +902,15 @@ def orbit_radius(nu: float, a: float, e: float) -> float:
|
|
|
792
902
|
-------
|
|
793
903
|
r : float
|
|
794
904
|
Orbital radius (km).
|
|
905
|
+
|
|
906
|
+
Examples
|
|
907
|
+
--------
|
|
908
|
+
>>> r = orbit_radius(0, 10000, 0.3) # At periapsis
|
|
909
|
+
>>> r
|
|
910
|
+
7000.0
|
|
911
|
+
>>> r = orbit_radius(np.pi, 10000, 0.3) # At apoapsis
|
|
912
|
+
>>> r
|
|
913
|
+
13000.0
|
|
795
914
|
"""
|
|
796
915
|
p = a * (1 - e * e)
|
|
797
916
|
return p / (1 + e * np.cos(nu))
|
|
@@ -812,6 +931,12 @@ def escape_velocity(r: float, mu: float = GM_EARTH) -> float:
|
|
|
812
931
|
-------
|
|
813
932
|
v_esc : float
|
|
814
933
|
Escape velocity (km/s).
|
|
934
|
+
|
|
935
|
+
Examples
|
|
936
|
+
--------
|
|
937
|
+
>>> v_esc = escape_velocity(6378 + 400) # At ISS altitude
|
|
938
|
+
>>> 10 < v_esc < 12 # About 11 km/s
|
|
939
|
+
True
|
|
815
940
|
"""
|
|
816
941
|
return np.sqrt(2 * mu / r)
|
|
817
942
|
|
|
@@ -831,6 +956,12 @@ def circular_velocity(r: float, mu: float = GM_EARTH) -> float:
|
|
|
831
956
|
-------
|
|
832
957
|
v_circ : float
|
|
833
958
|
Circular velocity (km/s).
|
|
959
|
+
|
|
960
|
+
Examples
|
|
961
|
+
--------
|
|
962
|
+
>>> v_circ = circular_velocity(6378 + 400) # At ISS altitude
|
|
963
|
+
>>> 7 < v_circ < 8 # About 7.7 km/s
|
|
964
|
+
True
|
|
834
965
|
"""
|
|
835
966
|
return np.sqrt(mu / r)
|
|
836
967
|
|