1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| """ AERIS-10 Python GUI 接口示例
功能: 1. 连接STM32串口获取目标数据 2. 实时显示目标在地图上的位置 3. 调整雷达参数(波形、PRF、CFAR阈值) """
import serial import threading import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation
class AERIS10Interface: """ AERIS-10 雷达控制与显示接口 通信协议: - 串口波特率: 921600 - 数据帧: [HEADER(2)] [AZIMUTH(2)] [RANGE(4)] [DOPPLER(2)] [SNR(2)] """ HEADER = bytes([0xAA, 0x55]) def __init__(self, port: str = '/dev/ttyUSB0', baud: int = 921600): self.serial = serial.Serial(port, baud, timeout=1.0) self.targets = [] self.running = False self.config = { 'pulse_width_us': 10, 'bandwidth_mhz': 100, 'prf_hz': 2000, 'cfar_threshold': 1e-6, 'beam_azimuth': 0, 'beam_elevation': 0 } def send_config(self, config: dict): """发送配置到STM32""" cmd = f"CFG,{config['prf_hz']},{config['pulse_width_us']},{config['bandwidth_mhz']}\n" self.serial.write(cmd.encode()) def set_beam_direction(self, azimuth: float, elevation: float): """设置波束方向(度)""" az_steps = int((azimuth + 45) / 90 * 127) el_steps = int((elevation + 45) / 90 * 127) cmd = f"BEAM,{az_steps},{el_steps}\n" self.serial.write(cmd.encode()) def parse_frame(self, data: bytes) -> dict: """解析目标数据帧""" if len(data) < 12: return None azimuth = int.from_bytes(data[2:4], 'little', signed=True) / 100.0 range_m = int.from_bytes(data[4:8], 'little') / 10.0 doppler = int.from_bytes(data[8:10], 'little', signed=True) / 10.0 snr = int.from_bytes(data[10:12], 'little') / 100.0 return { 'azimuth': azimuth, 'range': range_m, 'doppler': doppler, 'snr': snr } def receive_loop(self): """接收线程""" buffer = b'' while self.running: buffer += self.serial.read(self.serial.in_waiting or 1) while len(buffer) >= 12: if buffer[:2] == self.HEADER: target = self.parse_frame(buffer[:12]) if target: self.targets.append(target) buffer = buffer[12:] else: buffer = buffer[1:]
def demo_realtime_display(): """实时显示雷达目标""" radar = AERIS10Interface() radar.running = True thread = threading.Thread(target=radar.receive_loop, daemon=True) thread.start() fig, ax = plt.subplots(figsize=(10, 8), subplot_kw={'projection': 'polar'}) def update(frame): ax.clear() ax.set_theta_zero_location('N') ax.set_theta_direction(-1) ax.set_rlim(0, 3000) ax.set_xlabel('Range (m)') if radar.targets: azimuths = [np.radians(t['azimuth']) for t in radar.targets[-100:]] ranges = [t['range'] for t in radar.targets[-100:]] snrs = [t['snr'] for t in radar.targets[-100:]] scatter = ax.scatter(azimuths, ranges, c=snrs, cmap='viridis', s=50, vmin=0, vmax=30) plt.colorbar(scatter, ax=ax, label='SNR (dB)') ax.set_title('AERIS-10 Radar Display', pad=20) anim = FuncAnimation(fig, update, interval=100, cache_frame_data=False) plt.show() radar.running = False
if __name__ == "__main__": print("AERIS-10 Radar Interface Demo") print("=" * 40) demo_realtime_display()
|