math - GPS 'Submarine' 雷达检测其他位置

标签 math gps

假设我有一架无人机和我的手机。我看了看NORTH,并将无人机放置在我前方4米处。我应该看看雷达,看到无人机在北边的位置。

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

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

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 也是如此。由于无人机位于我的北方,像素 lat 应该更正吗?

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

非常感谢您的关注!

最佳答案

您要解决的一般问题是“投影”:将球体上的纬度/经度坐标投影到平面(屏幕)上。以下是有关如何解决该问题的问题/答案: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 就足够了:"Double precision floats give sub-millimetre precision anywhere on Earth."

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

关于math - GPS 'Submarine' 雷达检测其他位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30197324/

相关文章:

math - 如何将数字从基数 8 转换为基数 10?

python - 基于ELO的团队匹配算法

algorithm - 去除建筑物内不良的 GPS 信号

algorithm - 寻找航路点轨迹的最快部分

javascript - 哪些设备支持通过 navigator.geolocation 进行 Javascript 地理定位?

math - 为什么十进制数不能用二进制精确表示?

math - 如何计算流数据的变化率(导数)?

android - Google Play 商店为 SSL Handler cordova 应用程序 6.4.0 提供应用程序拒绝错误

math - float 学有问题吗?

android - 应用程序已在运行时激活 GPS