Map-baseret visuel navigation til Pi Zero 2W med simpelt kamera.
Kerneidé: Pre-processeret satellitkort onboard → kamera matcher features mod kortet → position + retning + hastighed.
Camera (640x480, nedad) Pre-processed map (5000 ORB features)
│ │
├─ ORB features (400/frame) ─────────┤
│ │
├─ FLANN LSH matching ───────────────┤
│ │
├─ Homography → Position on map ─────┤
│ │
├─ Optical flow → Velocity ──────────┤
│ │
└─ Kalman filter → Fused state ──────┤
│
Position, speed, heading
| Fil | Funktion |
|---|---|
feature_matcher.py |
ORB extract + FLANN match + homography |
map_prep.py |
Forbereder kort offline (desktop) |
visual_odometry.py |
Frame-til-frame tracking |
kalman_filter.py |
4-state Kalman (x,y,vx,vy) |
camera.py |
Pi Camera + simulator |
navigator.py |
Main engine — orkestrerer det hele |
demo_sim.py |
Demo med simuleret drone |
python map_prep.py omraade.png \
--corners 55.38,10.38 55.38,10.39 55.39,10.38 55.39,10.39 \
--features 5000Output: omraade_map.navmap (~200-400 KB for 5000 features)
# Med auto-genereret testkort:
python demo_sim.py
# Med eget kort:
python demo_sim.py omraade_map.navmap --altitude 50 --fps 5# Installer afhængigheder
pip install opencv-python numpy scipy picamera2
# Kopier .navmap fil til Pi'en
scp omraade_map.navmap pi@192.168.1.X:~/vision_nav/
# Kør navigation
python -c "
from navigator import VisualNavigator, NavConfig
from camera import PiCamera
cam = PiCamera(resolution=(640, 480), fps=5)
nav = VisualNavigator('omraade_map.navmap', cam, altitude_m=50)
while True:
state = nav.update()
if state:
lat, lon = nav.get_gps()
print(f'POS: {state.x_px:.0f},{state.y_px:.0f} | GPS: {lat:.5f},{lon:.5f} | {state.speed_ms:.1f} m/s')
"| Component | Tid (målt) |
|---|---|
| ORB extract (400 features) | ~60-80ms |
| ORB extract (map, 5000, once) | ~500ms |
| FLANN match (400 vs 5000) | ~40-60ms |
| Homography (RANSAC) | ~10-20ms |
| Total per frame | ~120-180ms |
| FPS | 5-8 FPS |
- Pixel → Meter: Via GSD (Ground Sampling Distance) fra kamera specs
- Pixel → GPS: Bilineær interpolation mellem 4 GPS-hjørner
- Hastighed: Fra Kalman-filter (position + odometry fusion)
- Nøjagtighed: 5-15m afhængigt af kortkvalitet og højde
Indbygget GSD-beregning for:
- Pi Camera v2 (IMX219, 8MP)
- Pi Camera v3 (IMX708, 12MP)
- ArduCam OV5647
from visual_odometry import CAMERA_PRESETS
gsd = CAMERA_PRESETS["pi_camera_v3"]["gsd_cm_per_px_m1"]
print(f"GSD: {gsd:.2f} cm/pixel @ 1m altitude")- Virker bedst med nedadvendt kamera (nadir)
- Kræver nogenlunde ens belysning mellem kort og flyvning
- Sæsonvariation (løvfald, sne) kan reducere matches
- Over vand/ørken: få features → dårligere tracking
- Ikke egnet til højhastighedsracing-droner (>15 m/s)
- AKAZE features for bedre scale invariance
- Multi-scale matching (pyramid)
- IMU fusion (accelerometer + gyro)
- Loop-closure detection
- ROS2 node wrapper
- MAVLink position output