<div align="center">

# 🎯 hawkeye

**Adaptive 2D Kalman Filter & Trajectory Predictor**

*Real-time object tracking with NIS-based adaptive process noise — designed for drones, robotics, and computer vision.*

![Python](https://img.shields.io/badge/Python-3.7%2B-blue?logo=python&logoColor=white)
![NumPy](https://img.shields.io/badge/Dependency-NumPy_Only-green?logo=numpy)
![License](https://img.shields.io/badge/License-MIT-yellow)
![Status](https://img.shields.io/badge/Status-Production_Ready-brightgreen)

</div>

---

## ✨ Why hawkeye?

| Feature | hawkeye | filterpy | pykalman |
|---|:---:|:---:|:---:|
| 6-state model (pos + vel + accel) | ✅ | Manual setup | Manual setup |
| NIS-based adaptive Q matrix | ✅ | ❌ | ❌ |
| Auto maneuver detection | ✅ | ❌ | ❌ |
| Trajectory prediction (polyfit) | ✅ | ❌ | ❌ |
| Confidence scoring | ✅ | ❌ | ❌ |
| Covariance ellipse (visualization) | ✅ | ❌ | ❌ |
| Zero config needed | ✅ | ❌ | ❌ |
| Lightweight (2 files, ~400 lines) | ✅ | ❌ | ❌ |

> Most Kalman filter libraries give you the math primitives. **hawkeye gives you a ready-to-use 2D tracker** that handles real-world situations like sudden maneuvers, occlusions, and noisy sensors out of the box.

---

## 📦 Installation

```bash
pip install hawkeye
```

Or install from source:
```bash
git clone https://github.com/ByIbos/hawkeye.git
cd hawkeye
pip install -e .
```

---

## 🚀 Quick Start

### Basic Tracking
```python
from hawkeye import KalmanFilter2D

# Create filter (30 FPS video)
kf = KalmanFilter2D(dt=1/30)

# Initialize with first detection
kf.init_state(x=320, y=240)

# Every frame:
px, py = kf.predict()         # Predict next position
fx, fy = kf.update(325, 238)  # Correct with measurement

print(f"Position: ({fx:.1f}, {fy:.1f})")
print(f"Speed: {kf.speed:.1f} px/frame")
print(f"Confidence: {kf.confidence:.0%}")
```

### Handling Occlusions (No Measurement)
```python
# When the target is hidden behind an obstacle:
for frame in occluded_frames:
    px, py = kf.predict()  # Just predict, don't update!
    # The Kalman filter will coast using velocity + acceleration
    # Confidence will gradually decrease
    print(f"Predicted: ({px:.1f}, {py:.1f}) | Conf: {kf.confidence:.0%}")

# When the target reappears:
fx, fy = kf.update(new_x, new_y)  # Snap back to reality
```

### Trajectory Prediction
```python
from hawkeye import KalmanFilter2D, TrajectoryPredictor

kf = KalmanFilter2D(dt=1/30)
tp = TrajectoryPredictor(min_points=10, predict_frames=45)

# After tracking for a while...
kf.init_state(100, 200)
for x, y in detections:
    kf.predict()
    kf.update(x, y)

# Predict future path (1.5 seconds ahead)
future_path = tp.predict(kf.position_history)
print(f"Prediction confidence: {tp.confidence:.0%}")

# Draw the predicted trajectory
for point in future_path:
    draw_point(point)  # Your visualization function
```

### Adaptive Behavior (Maneuver Detection)
```python
kf = KalmanFilter2D(dt=1/30, process_noise=1.0)

# During normal flight → filter is tight, smooth output
# During sharp turn → NIS spikes → Q auto-scales → filter loosens
# After maneuver → Q gradually returns to normal

# You can monitor the adaptation:
print(f"Adaptive scale: {kf.adaptive_scale:.1f}")  # 1.0 = normal, >5 = maneuver
print(f"NIS history: {list(kf.nis_history)}")
```

---

## 🔧 API Reference

### `KalmanFilter2D(dt, process_noise, measurement_noise)`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `dt` | float | 1/30 | Time step between frames (seconds) |
| `process_noise` | float | 1.0 | Base process noise (higher = more responsive) |
| `measurement_noise` | float | 5.0 | Measurement noise (higher = smoother) |

#### Methods

| Method | Returns | Description |
|---|---|---|
| `init_state(x, y)` | None | Initialize with first measurement |
| `predict()` | (x, y) | Predict next state |
| `update(z_x, z_y)` | (x, y) | Correct with measurement |
| `reset()` | None | Reset to uninitialized |

#### Properties

| Property | Type | Description |
|---|---|---|
| `position` | (x, y) | Current position estimate |
| `velocity` | (vx, vy) | Current velocity (px/frame) |
| `acceleration` | (ax, ay) | Current acceleration (px/frame²) |
| `speed` | float | Speed magnitude |
| `confidence` | float | Confidence score [0.0 - 1.0] |
| `position_history` | deque | Past positions (max 120) |
| `covariance_ellipse()` | (w, h, angle) | 95% confidence ellipse |

### `TrajectoryPredictor(min_points, predict_frames, poly_degree)`

| Parameter | Type | Default | Description |
|---|---|---|---|
| `min_points` | int | 10 | Minimum points needed |
| `predict_frames` | int | 45 | Frames to predict ahead |
| `poly_degree` | int | 2 | Polynomial degree (2=quadratic) |

#### Methods

| Method | Returns | Description |
|---|---|---|
| `predict(history)` | [(x,y), ...] | Predict future path from position history |
| `reset()` | None | Clear stored predictions |

---

## 🎯 Use Cases

- **🚁 Drone Tracking** — Track aerial targets with sudden maneuvers
- **🤖 Robot Navigation** — Smooth sensor fusion for SLAM pipelines
- **📹 Video Surveillance** — Persistent object tracking through occlusions
- **🎮 Game AI** — Predict player/NPC trajectories
- **🛰️ Satellite Tracking** — 2D angular tracking of orbital objects

---

## 📐 How It Works

```
┌─────────────────────────────────────────────────┐
│              hawkeye Pipeline                  │
│                                                 │
│   Measurement ──→ Innovation ──→ NIS Check      │
│       (x,y)         (y=z-Hx)     │             │
│                                  ↓              │
│                          ┌───────────────┐      │
│                          │ NIS > 5.99?   │      │
│                          │ (Maneuver!)   │      │
│                          └───┬─────┬─────┘      │
│                          Yes │     │ No         │
│                              ↓     ↓            │
│                         Scale Q   Shrink Q      │
│                          * 1.5     * 0.85       │
│                              │     │            │
│                              ↓     ↓            │
│                     Kalman Update (K, P, x)     │
│                              │                  │
│                              ↓                  │
│                     Filtered Position ──→ Output │
│                              │                  │
│                              ↓                  │
│                     History Buffer              │
│                              │                  │
│                              ↓                  │
│                     Trajectory Prediction        │
│                     (Polynomial Extrapolation)   │
└─────────────────────────────────────────────────┘
```

---

## 📜 License

MIT License — use it anywhere, commercially or personally.

---

<div align="center">
<i>Built with ❤️ by <a href="https://github.com/ByIbos">ByIbos</a> — extracted from the <a href="https://github.com/ByIbos/Auto-ReID-Drone-Tracker">Auto-ReID Drone Tracker</a> project.</i>
</div>
