Library Architecture

Overview

The Tracker Component Library contains 153 modules organized into 8 major subsystems:

Architecture diagram showing subsystem organization
  1. Dynamic Estimation (15 modules) - Filtering and state estimation

  2. Data Association (8 modules) - Assignment and correlation algorithms

  3. Coordinate Systems (20 modules) - Conversions and transformations

  4. Dynamic Models (12 modules) - Motion models and process noise

  5. Navigation (18 modules) - INS, guidance, geodesy

  6. Geophysical (15 modules) - Gravity, magnetism, weather, terrain

  7. Tracking (12 modules) - Multi-target tracking and containers

  8. Mathematical (25 modules) - Special functions, distributions, integration

High-Level Subsystem View

pytcl/
├── core/                          # Utility: types, decorators, constants
├── containers/                    # Data structures: TrackSet, EstimationSet
│
├── dynamic_estimation/            # Filtering engines
│   ├── kalman/                    # KF, EKF, UKF, CKF, IMM
│   ├── particle_filters/          # PF, SISR, SIR
│   ├── batch_estimation/          # Least squares, smoothing
│   └── measurement_update/        # Update equations
│
├── dynamic_models/                # Motion models
│   ├── continuous_time/           # White noise acc, Gauss-Markov
│   ├── discrete_time/             # CT to DT conversions
│   └── process_noise/             # Q matrix generation
│
├── assignment_algorithms/         # Data association
│   ├── two_dimensional/           # 2D assignment
│   ├── three_dimensional/         # 3D/MHT assignment
│   └── optimization/              # Hungarian, auction, Murty
│
├── trackers/                      # Tracker implementations
│   └── multi_tracker_gnn/         # GNN tracker
│
├── coordinate_systems/            # Coordinate transformations
│   ├── conversions/               # Cart↔spherical, geodetic, etc
│   ├── rotations/                 # Euler angles, quaternions, DCM
│   ├── jacobians/                 # Partial derivatives
│   └── projections/               # Map projections (UTM, Mercator)
│
├── navigation/                    # Navigation
│   ├── geodesy/                   # Great circle, rhumb line
│   ├── ins_gnss/                  # INS mechanization
│   ├── ephemerides/               # JPL ephemerides
│   └── tdoa/                      # Time difference of arrival
│
├── geophysical/                   # Environmental models
│   ├── gravity/                   # WGS84, EGM96/2008
│   ├── magnetism/                 # WMM, IGRF
│   ├── atmosphere/                # NRLMSISE00
│   └── terrain/                   # Terrain elevation
│
├── astronomical/                  # Orbital mechanics
│   ├── orbital_mechanics/         # Keplerian propagation
│   ├── lambert/                   # Lambert's problem
│   ├── reference_frames/          # ECEF↔ECI, precession, nutation
│   ├── relativity/                # Relativistic corrections
│   ├── sgp4/                      # SGP4 propagator
│   └── ephemeris/                 # Ephemeris functions
│
├── mathematical_functions/        # Math utilities
│   ├── special_functions/         # Marcum Q, Lambert W, Bessel
│   ├── distributions/             # Probability distributions
│   ├── statistics/                # Statistical functions
│   ├── numerical/                 # Integration, interpolation
│   └── optimization/              # Minimization, root finding
│
├── signal_processing/             # Signal processing
│   ├── filtering/                 # IIR, FIR filters
│   ├── detection/                 # CFAR, matched filtering
│   └── transforms/                # FFT, wavelets
│
├── clustering/                    # Pattern recognition
│   └── algorithms/                # K-means, DBSCAN, hierarchical
│
├── performance_evaluation/        # Metrics and analysis
│   ├── metrics/                   # NEES, NIS, Cramer-Rao
│   ├── consistency/               # Filter consistency checks
│   └── benchmarking/              # Performance profiling
│
├── gpu/                           # GPU acceleration
│   ├── cupy_backend/              # NVIDIA acceleration
│   └── mlx_backend/               # Apple Silicon acceleration
│
└── plotting/                      # Visualization

Subsystem Details

Dynamic Estimation Subsystem

Purpose: Implement state estimation algorithms (filtering).

When to use: Any system where you need to estimate hidden state from noisy measurements.

Modules:

  • kalman - Linear/nonlinear Kalman variants (KF, EKF, UKF, CKF)

  • particle_filters - Nonlinear, non-Gaussian filtering

  • batch_estimation - Offline smoothing and batch processing

  • measurement_update - Generic update equations

Quick Example:

import numpy as np
from pytcl.dynamic_estimation.kalman import KalmanFilter
from pytcl.dynamic_models import f_constant_velocity, q_constant_velocity

# Setup filter
T = 0.1  # time step
x = np.array([0, 1, 0, 0])  # state: pos, vel (2D)
P = np.eye(4) * 0.1

F = f_constant_velocity(T, num_dims=2)
Q = q_constant_velocity(T, sigma_a=0.1, num_dims=2)
H = np.eye(2, 4)  # observe position
R = np.eye(2) * 0.5

kf = KalmanFilter(F, H, Q, R)

# Predict and update
measurements = [np.array([1.1, 0.5]), np.array([2.3, 1.2]), ...]
for z in measurements:
    x, P = kf.predict(x, P)
    x, P = kf.update(x, P, z)
Dependency Graph:
  • Requires: dynamic_models (F, Q matrices)

  • Requires: coordinate_systems (if fusing different coordinate types)

  • Optional: performance_evaluation (diagnostic metrics)

Data Association Subsystem

Purpose: Match observations (measurements) to tracks (targets).

When to use: Multi-target tracking with multiple sensors or measurement ambiguity.

Modules:

  • two_dimensional - 2D assignment (gating, MHT)

  • three_dimensional - 3D assignment, Murty algorithm

  • optimization - Hungarian, auction algorithms

Quick Example:

from pytcl.assignment.optimization import assignment_nd
from scipy.spatial.distance import cdist

# Compute cost matrix (lower = better match)
positions = np.array([[0, 0], [1, 1], [2, 2]])  # 3 targets
measurements = np.array([[0.1, 0.1], [2.1, 2.1]])  # 2 measurements

cost = cdist(positions[:, :2], measurements, metric='euclidean')
cost[cost > 0.5] = np.inf  # gate: only close matches

# Solve assignment
assignments = assignment_nd(cost)  # [(target_i, meas_j), ...]
Dependency Graph:
  • Requires: Computed cost matrix (usually from coordinate_systems)

  • Optional: clustering (pre-grouping tracks)

Coordinate Systems Subsystem

Purpose: Transform between different coordinate representations and reference frames.

When to use: Working with data from different sensors or coordinate systems.

Modules:

  • conversions - Spherical ↔ Cartesian, geodetic, RUV, ENU

  • rotations - Euler angles, quaternions, rotation matrices (DCM)

  • jacobians - Partial derivatives for Jacobian matrices

  • projections - Map projections (UTM, Mercator, Lambert Conformal)

Quick Example:

from pytcl.coordinate_systems.conversions import sphere2cart, cart2sphere
from pytcl.coordinate_systems.rotations import euler2dcm

# Spherical to Cartesian
spherical = np.array([1.0, np.pi/4, np.pi/6])  # range, az, el
cartesian = sphere2cart(spherical)

# Rotation
euler = np.array([0, 0, np.pi/4])  # heading, pitch, roll
DCM = euler2dcm(euler)
Dependency Graph:
  • Depends on: mathematical_functions (for special functions)

  • Used by: Virtually all other subsystems

  • Provides: Jacobians for dynamic_estimation

Geophysical Subsystem

Purpose: Model environmental factors (gravity, magnetic field, atmosphere, terrain).

When to use: Accurate modeling of forces on vehicles, environmental corrections.

Modules:

  • gravity - WGS84 ellipsoid, EGM96/2008 geoid, gravity anomalies

  • magnetism - World Magnetic Model (WMM), IGRF

  • atmosphere - NRLMSISE-00 model for density, temperature

  • terrain - Terrain elevation from digital elevation models

Quick Example:

from pytcl.gravity.gravity_models import gravity_force
from pytcl.magnetism.magnetic_models import magnetic_field
from pytcl.atmosphere.nrlmsise00 import atmospheric_density

# Compute gravitational acceleration
ecef_pos = np.array([6378000, 0, 0])  # Earth surface
g_accel = gravity_force(ecef_pos)  # m/s^2

# Magnetic field
mag_field = magnetic_field(ecef_pos)  # nT

# Atmospheric density
lat, lon, alt = 40.0, -74.0, 35000  # 35,000 feet
rho = atmospheric_density(lat, lon, alt)
Dependency Graph:
  • Depends on: coordinate_systems, mathematical_functions

  • Used by: navigation, astronomical (for satellite propagation)

Astronomical Subsystem

Purpose: Orbital mechanics, ephemerides, and celestial reference frames.

When to use: Satellite operations, space vehicle navigation, astronomical calculations.

Modules:

  • orbital_mechanics - Keplerian propagation, anomaly conversions

  • lambert - Lambert’s problem (bi-elliptic solutions)

  • reference_frames - ECEF↔ECI, precession, nutation, polar motion

  • relativity - Relativistic corrections (Schwarzschild, Shapiro delay)

  • sgp4 - SGP4 propagator with perturbations

  • ephemeris - JPL ephemeris interface

Quick Example:

from pytcl.astronomical.orbital_mechanics import propagate_kepler
from pytcl.astronomical.reference_frames import ecef2eci, eci2ecef

# Keplerian propagation
semimajor_axis = 6800e3  # meters
eccentricity = 0.001
inclination = 98.0  # degrees (sun-synchronous)

state = np.array([semimajor_axis, eccentricity, inclination,
                  0, 0, 0])  # Keplerian elements

# Propagate 1 hour
state_prop = propagate_kepler(state, t=3600)
Dependency Graph:
  • Depends on: coordinate_systems, navigation, geophysical

  • Used by: Satellite tracking systems

  • Provides: Ephemeris data to navigation systems

Mathematical Functions Subsystem

Purpose: Special functions, probability distributions, numerical methods.

When to use: Implementing advanced algorithms (Bessel functions, special distributions).

Modules:

  • special_functions - Marcum Q, Lambert W, Bessel, hypergeometric

  • distributions - Rayleigh, Rician, non-central chi-square

  • statistics - Statistical tests, confidence intervals

  • numerical - Integration, interpolation, root finding

  • optimization - Minimization, root solving

Quick Example:

from pytcl.mathematical_functions.special_functions import (
    marcum_q, lambert_w
)
from pytcl.mathematical_functions.distributions import (
    rician_pdf, rayleigh_pdf
)

# Marcum Q function (detection probability)
a, b = 2.0, 3.0
q_val = marcum_q(a, b)  # Detection probability

# Rician distribution (fading signals)
signal = 1.0
noise = 0.5
x = 2.0
pdf_val = rician_pdf(x, signal, noise)
Dependency Graph:
  • Depends on: NumPy, SciPy (foundation)

  • Used by: Nearly all other subsystems

Tracking Subsystem

Purpose: Multi-target tracking implementations and related containers.

When to use: Building complete tracking systems from filters and association.

Modules:

  • multi_tracker_gnn - Global Nearest Neighbor tracker

  • containers - TrackSet, EstimationSet data structures

  • clustering - Track clustering algorithms

Quick Example:

from pytcl.trackers.multi_tracker_gnn import GNNTracker
from pytcl.containers import TrackSet, Track

# Create tracker
tracker = GNNTracker(
    gate_threshold=5.0,
    new_track_threshold=3,
    delete_threshold=5
)

# Process measurements
for measurements in measurement_stream:
    tracks = tracker.update(measurements)
Dependency Graph:
  • Depends on: dynamic_estimation, assignment_algorithms, coordinate_systems

  • Used by: Complete tracking applications

Common Architecture Patterns

Pattern 1: Single-Target Tracking

Use Case: Tracking one object with one or more sensors.

Workflow:

# 1. Get measurements
measurements = sensor.get_observations()

# 2. Convert to common frame
from pytcl.coordinate_systems import sphere2cart
cartesian_meas = sphere2cart(measurements)

# 3. Filter update
from pytcl.dynamic_estimation.kalman import kf_predict, kf_update
x_pred, P_pred = kf_predict(x, P, F, Q)
x_upd, P_upd = kf_update(x_pred, P_pred, cartesian_meas, H, R)
Modules Used:
  • dynamic_estimation: Filter

  • dynamic_models: Motion model (F, Q)

  • coordinate_systems: Measurement conversion

Pattern 2: Multi-Target Tracking with Assignment

Use Case: Tracking multiple targets with data association.

Workflow:

# 1. Predict all tracks
for track in tracks:
    track.x_pred, track.P_pred = kf_predict(track.x, track.P, F, Q)

# 2. Compute assignment cost
from scipy.spatial.distance import cdist
positions = np.array([t.x_pred[:2] for t in tracks])
measurements = get_measurements()
cost = cdist(positions, measurements)
cost[cost > gate_dist] = np.inf

# 3. Solve assignment
from pytcl.assignment.optimization import assignment_nd
assignments = assignment_nd(cost)

# 4. Update assigned tracks
for track_idx, meas_idx in assignments:
    if meas_idx >= 0:
        x_upd, P_upd = kf_update(
            tracks[track_idx].x_pred,
            tracks[track_idx].P_pred,
            measurements[meas_idx],
            H, R
        )
Modules Used:
  • dynamic_estimation: Filter

  • assignment_algorithms: Data association

  • coordinate_systems: Gating

Pattern 3: INS/GNSS Navigation

Use Case: Fusing inertial and GPS data for robust navigation.

Workflow:

from pytcl.navigation.ins_gnss import ins_update, gnss_update

# 1. IMU propagation (continuous)
accel, gyro = imu.read()
state, covariance = ins_update(state, covariance, accel, gyro, dt)

# 2. GPS update (intermittent)
if gps.has_fix():
    gnss_pos = gps.get_position()
    state, covariance = gnss_update(state, covariance, gnss_pos, gnss_std)
Modules Used:
  • navigation: INS mechanization

  • dynamic_estimation: Filter equations

  • coordinate_systems: Frame conversions

Pattern 4: Satellite Propagation with Corrections

Use Case: Accurate satellite orbit prediction.

Workflow:

from pytcl.astronomical.orbital_mechanics import propagate_kepler
from pytcl.astronomical.reference_frames import ecef2eci
from pytcl.geophysical.gravity import perturbations

# 1. Initial state in ECI
state_eci = get_initial_state()

# 2. Propagate with perturbations
for t in time_steps:
    # Keplerian propagation
    state_eci = propagate_kepler(state_eci, dt)

    # Apply perturbations
    perturbations_eci = perturbations(state_eci)
    state_eci += perturbations_eci * dt

# 3. Convert to ECEF for ground tracking
state_ecef = ecef2eci(state_eci)
Modules Used:
  • astronomical: Orbit propagation

  • geophysical: Environmental effects

  • coordinate_systems: Frame conversions

Dependency Resolution Guide

Question: How do I find what modules I need?

Answer: Follow this decision tree:

  1. Are you doing state estimation?

    → YES: Use dynamic_estimation

    • Need motion model? → Use dynamic_models

    • Need to convert measurements? → Use coordinate_systems

  2. Are you tracking multiple targets?

    → YES: Use assignment_algorithms

    • Need advanced assignment? → Use three_dimensional

  3. Are you working with different coordinate systems?

    → YES: Use coordinate_systems

    • Need rotations? → Use rotations

    • Need projections? → Use projections

  4. Are you doing navigation?

    → YES: Use navigation

    • Need geodetic calculations? → Use geodesy

    • Need INS/GNSS fusion? → Use ins_gnss

    • Need satellite operations? → Use astronomical

  5. Do you need environmental modeling?

    → YES: Use geophysical

    • Gravity effects? → Use gravity

    • Magnetic field? → Use magnetism

    • Atmospheric? → Use atmosphere

Module Import Patterns

Single Function Import (for specific use):

from pytcl.coordinate_systems.conversions import sphere2cart
result = sphere2cart(data)

Submodule Import (for multiple related functions):

from pytcl.dynamic_estimation import kalman
x_pred, P_pred = kalman.kf_predict(x, P, F, Q)

Top-Level Import (for convenience):

import pytcl
result = pytcl.sphere2cart(data)  # If re-exported

Check available functions in module:

import pytcl.coordinate_systems.rotations as rotations
print([name for name in dir(rotations) if not name.startswith('_')])

Best Practices by Use Case

Rapid Prototyping

→ Use top-level functions, simple examples

Production Tracking System

→ Use trackers.multi_tracker_gnn directly → Add diagnostic checks from performance_evaluation

Research/Development

→ Use individual modules for maximum flexibility → Combine filters with custom models

High-Performance Real-Time

→ Use GPU acceleration (gpu module) → Pre-compute Jacobians → Use Numba-accelerated functions → See Performance Optimization Guide

Safety-Critical Systems

→ Use consistency checks from performance_evaluation → Monitor NEES/NIS values → Use multiple independent filters for voting → Validate with kalman_filter_tuning diagnostics

See Also