liusuyi
2026-06-11 b097f7539a7429a85cdda7959c9ecb83a37a2918
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
package com.ard.work.service.impl;
 
import com.ard.work.domain.cache.UavTelemetryDataCache;
import com.ard.work.domain.dto.telemetry.TelemetryData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
 
/**
 * 无人机位置变化判断服务
 *
 * @author 刘苏义
 */
@Slf4j
@Service
public class UavPositionChangeService {
 
    // 位置变化阈值(米)
    private static final double POSITION_CHANGE_THRESHOLD = 5.0;
    
    // 无效坐标的默认值
    private static final double INVALID_COORD = 0.0;
 
    /**
     * 判断是否需要触发区域检测
     * @param telemetryData 当前遥测数据
     * @return true-需要触发区域检测,false-不需要
     */
    public boolean shouldTriggerRegionCheck(TelemetryData telemetryData) {
        String boxSn = telemetryData.getBoxSn();
        
        // 获取上次遥测数据
        TelemetryData lastData = UavTelemetryDataCache.get(boxSn);
        
        // 首次上报,需要检测
        if (lastData == null) {
            log.debug("无人机 {} 首次上报,触发区域检测", boxSn);
            return true;
        }
        
        // 判断位置是否变化
        return isPositionChanged(lastData, telemetryData);
    }
    
    /**
     * 判断位置是否发生变化
     */
    private boolean isPositionChanged(TelemetryData lastData, TelemetryData newData) {
        double lastLng = lastData.getLng();
        double lastLat = lastData.getLat();
        double newLng = newData.getLng();
        double newLat = newData.getLat();
        
        // 坐标无效(为0),认为需要检测
        if (lastLng == INVALID_COORD || lastLat == INVALID_COORD || 
            newLng == INVALID_COORD || newLat == INVALID_COORD) {
            log.debug("坐标无效,触发区域检测");
            return true;
        }
        
        // 计算移动距离
        double distance = calculateDistance(lastLat, lastLng, newLat, newLng);
        
        boolean changed = distance > POSITION_CHANGE_THRESHOLD;
        
        if (changed) {
            log.debug("无人机 {} 移动了 {:.2f} 米,触发区域检测", newData.getBoxSn(), distance);
        }
        
        return changed;
    }
    
    /**
     * 计算两点间距离(米)- Haversine公式
     */
    private double calculateDistance(double lat1, double lng1, double lat2, double lng2) {
        double earthRadius = 6371000; // 地球半径(米)
        
        double dLat = Math.toRadians(lat2 - lat1);
        double dLng = Math.toRadians(lng2 - lng1);
        
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                   Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                   Math.sin(dLng / 2) * Math.sin(dLng / 2);
        
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        
        return earthRadius * c;
    }
}