假设我有一架无人机和我的手机。我看了看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/