【问题标题】:GPS 'Submarine' Radar Detecting Other locationGPS“潜艇”雷达探测其他位置
【发布时间】:2015-05-12 17:07:04
【问题描述】:

假设我有一架无人机和我的手机。我看了看北方,把无人机放在我前面 4 米处。我应该看看雷达,看到无人机在北方。

我的雷达是 256x256 像素,无人机的最大距离是 200 米,大约是 0.002 纬度/经度。

所以,我做了一个简单的测试类来测试我北方的这架无人机。

public static void main(String[] args) {

    BigDecimal droneLat = new BigDecimal(-22.811468333334087077446383773349225521087646484375);
    BigDecimal droneLong = new BigDecimal(-47.04746500000123177187560941092669963836669921875);

    BigDecimal phoneLat = new BigDecimal(-22.81129370000000022855601855553686618804931640625); 
    BigDecimal phoneLong = new BigDecimal(-47.04832809999999909678081166930496692657470703125);

    BigDecimal latDiff = phoneLat.subtract(droneLat);
    BigDecimal longDiff = phoneLong.subtract(droneLong);

    int pixelsLat = degreesToPixels265x265(latDiff.abs());
    int pixelsLong = degreesToPixels265x265(longDiff.abs());

     if (latDiff.compareTo(new BigDecimal(0)) < 0) { // drone > phone means phone is farther to north, phone lat will be lower, it will show lower in radar
           pixelsLat = -pixelsLat;
     }
     if (longDiff.compareTo(new BigDecimal(0)) > 0) { // drone > phone means phone is farther to north, phone lat will be lower, it will show lower in radar
           pixelsLong = -pixelsLong;
     }

    System.out.println("DiffLat "+latDiff);
    System.out.println("DiffLong "+longDiff);

    System.out.println("Pixels lat = "+pixelsLat);
    System.out.println("Pixels long = "+pixelsLong);
}

public static int degreesToPixels265x265(BigDecimal n) {
    BigDecimal p1 = n.multiply(new BigDecimal(256/2)); 
    return p1.divide(new BigDecimal(0.002d),2,BigDecimal.ROUND_CEILING).intValue();
}

Pixels Lat 的总和为 128 以绘制无人机位置,pixelsLong 也是如此。由于无人机在我的北方,像素纬度应该更正吗?

我在这里做一些错误的数学运算来检测绘制这个的真实坐标吗?

非常感谢您的关注!

【问题讨论】:

    标签: math gps


    【解决方案1】:

    您要解决的一般问题是“投影”:将球体上的纬度/经度坐标投影到平面(屏幕)上。这是关于如何解决该问题的问题/答案:Converting longitude/latitude to X/Y coordinate

    但是如果您不关心解决投影的一般问题,对于任何投影(墨卡托等)并处理非常长的距离(数千英里)和边缘情况(您在靠近北方或南方飞行杆),您可以做一些非常简单的事情:计算点 A(您的位置)和点 B(无人机的位置)的方位和距离。使用该方位和距离,在屏幕上绘制无人机的近似值,该近似值应该可以在几百米范围内正常工作。

    要计算距离,请使用Haversine formula

    public static double distance(double lat1, double lon1, double lat2, double lon2) {
        double R = 6372.8; // Radius of the earth in kilometers.
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);
        lat1 = Math.toRadians(lat1);
        lat2 = Math.toRadians(lat2);
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
        double c = 2 * Math.asin(Math.sqrt(a));
        return R * c;
    }
    

    并且要计算两点之间的角度(实际上只是初始角度——在球体上,角度会随着您的靠近而变化,但我们是在短距离内进行近似):

    public static double bearing(double lat1, double lon1, double lat2, double lon2) {
        double latitude1 = Math.toRadians(lat1);
        double latitude2 = Math.toRadians(lat2);
        double longitude1 = Math.toRadians(lon1);
        double longitude2 = Math.toRadians(lon2);
        double longDiff = longitude2 - longitude1;
        double y = Math.sin(longDiff) * Math.cos(latitude2);
        double x = Math.cos(latitude1) * Math.sin(latitude2) - Math.sin(latitude1) * Math.cos(latitude2) * Math.cos(longDiff);
        return Math.atan2(y, x);
    }
    

    一旦您可以计算距离和方位,您就可以将其映射到您的屏幕上(您正在做的是将极坐标转换为笛卡尔/XY 坐标):

    public static void plotLatLon(double droneLat, double droneLon) {
        // Get location from phone geolocation.
        double phoneLat = -22.8112937000;
        double phoneLon = -47.0483281000;
        int width = 256;
        int height = 256;
        // 256 pixels = 400 meters; 200 meters away = edge of screen.
        double scaleFactor = 256.0 / 400.0;
    
        double bearing = bearing(phoneLat, phoneLon, droneLat, droneLon);
        double distance = distance(phoneLat, phoneLon, droneLat, droneLon);
        System.out.println("Bearing: " + (Math.toDegrees(bearing) + 360.0) % 360.0);
        System.out.println("Distance: " + distance);
        double angle = (Math.PI / 2.0) - bearing;
        int x = (int)(distance * scaleFactor * Math.cos(angle));
        int y = (int)(distance * scaleFactor * Math.sin(angle));
        // Assumes radar coordinate system has (0,0) at the lower left.
        Radar.plotXY(x + width / 2, y + height / 2);
    }
    

    这是我得到的结果:

    Bearing: 102.38029388096368
    Distance: 90.59766443003579
    X: 184
    Y: 116
    

    (您的无人机实际上并不在北方;您提供的坐标将其置于东方和稍微南方。)

    注意双精度就足够了:"Double precision floats give sub-millimetre precision anywhere on Earth."

    您可能还对像 spatial4j 这样的库感兴趣,用于在 Java 中进行地理计算。

    【讨论】:

      【解决方案2】:

      当您向北行驶时,北极的纬度最多增加 90 度。所以是的,你是对的。像素应该更积极。 (我猜你在北美/欧洲?)Read This

      但是,我现在正在做一个 GPS 项目,我可以根据经验告诉您,4 米远,远未接近。民用 GPS 接收器没有蜂窝塔的帮助在理想条件下可以达到大约 10 米的精度。使用 GLONASS 可能会更好。

      如果您愿意等待,可以购买其中一种: http://store.swiftnav.com

      GPS 101:将无人机移到更远的地方,并考虑仅精确到 20 米左右的结果。

      【讨论】:

        猜你喜欢
        • 2016-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-31
        • 2018-12-30
        • 1970-01-01
        • 1970-01-01
        • 2016-10-31
        相关资源
        最近更新 更多