GPS'潜艇'雷达探测其他位置

时间:2015-05-12 17:07:05

标签: math gps

让我们说我有一架无人机和我的手机。我看着北方,把无人机放在我前面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();
}

像素纬度将总和为128以绘制无人机位置,因此是像素长度。由于无人机在我的北方,像素应该更积极吗?

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

非常感谢您的关注!

2 个答案:

答案 0 :(得分:2)

您尝试解决的一般问题是&#34;投影&#34;:将球体上的纬度/经度坐标投影到平面(屏幕)上。以下是关于如何解决该问题的问题/答案:Converting longitude/latitude to X/Y coordinate

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

要计算距离,请使用Haversine formula

.burst-12 {
width: 80px;
height: 80px;
text-align: center;
position: absolute;
left:50px;
opacity: .8;
top:100px;
border-radius: 17px;
-moz-border-radius: 17px;
-webkit-border-radius: 15 16 17 18px;
}

.burst-12:before, .burst-12:after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 80px;
background: inherit;
}

.burst-12:before {
-webkit-transform: rotate(30deg);
   -moz-transform: rotate(30deg);
    -ms-transform: rotate(30deg);
     -o-transform: rotate(30deg);
border-radius: 18px;
-moz-border-radius: 18px;
-webkit-border-radius: 18 19 17 16px;
}

.burst-12:after {
-webkit-transform: rotate(60deg);
   -moz-transform: rotate(60deg);
    -ms-transform: rotate(60deg);
     -o-transform: rotate(60deg);
border-radius: 19px;
-moz-border-radius: 19px;
-webkit-border-radius: 19 10 11 16px;
}

.x1{
  background: #f64260;
}

.x2{
background: #f8605b;
left:123px;
-webkit-transform: rotate(15deg);
   -moz-transform: rotate(15deg);
    -ms-transform: rotate(15deg);
     -o-transform: rotate(15deg);
}

.x1:hover{
background-color:#94dbdd;
-webkit-transform: rotate(300deg);
   -moz-transform: rotate(300deg);
    -ms-transform: rotate(300deg);
     -o-transform: rotate(300deg);
}

.x2:hover{
background-color:#4c6278;
-webkit-transform: rotate(360deg);
   -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
     -o-transform: rotate(360deg);
}

.x3 {
background-color: sandybrown;
left:190px;
-webkit-transform: rotate(10deg);
   -moz-transform: rotate(10deg);
    -ms-transform: rotate(10deg);
     -o-transform: rotate(10deg);
}

.x3:hover{
background-color:cornflowerblue;  
-webkit-transform: rotate(360deg);
   -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
     -o-transform: rotate(360deg);
}

.x4{
background-color: #f1ce4b;
left:260px;
-webkit-transform: rotate(10deg);
   -moz-transform: rotate(10deg);
    -ms-transform: rotate(10deg);
     -o-transform: rotate(10deg);
}

.x4:hover{
background-color:#305578;
-webkit-transform: rotate(360deg);
   -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
     -o-transform: rotate(360deg);
}

.burst-12 span{
 display:block;
 position:absolute;
 z-index:2;
}

p:first-letter{
text-transform: uppercase;
}

p {
color: white;
font-family: "Adobe Caslon Pro", "Hoefler Text", Georgia, Garamond, Times,     serif;
letter-spacing:0.1em;
text-align:center;
margin: 30px auto;
text-transform: lowercase;
line-height: 145%;
font-size: 14pt;
font-variant: small-caps;
border-style:solid;
border-width: 1px;
padding: 4px;
}

要计算两点之间的角度(实际上只是初始角度 - 在球体上,角度随着距离越近而变化,但我们在短距离内近似):

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;
}

一旦你可以计算距离&amp;轴承,你可以将它映射到你的屏幕上(你正在做的是将极坐标转换为笛卡尔坐标/ XY坐标):

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);
}

以下是我得到的结果:

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);
}

(你的无人机实际上并不在北方;你给它的坐标位于东边和南边。)

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

您可能也对像spatial4j这样的库感兴趣,可以用Java进行地理计算。

答案 1 :(得分:0)

当你向北移动时,北极的纬度增加到90度。是的,你是对的。像素应该更积极。 (我假设您在北美/欧洲?)Read This

但是,我现在正在开展一个GPS项目,我可以从经验告诉你,4米远远不能靠近。未经电池塔协助的民用GPS接收器可在理想条件下达到约10米的精度。使用GLONASS可能更好。

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

GPS 101:将无人机移动得更远,并考虑到仅精确到约20米的结果。