让我们说我有一架无人机和我的手机。我看着北方,把无人机放在我前面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以绘制无人机位置,因此是像素长度。由于无人机在我的北方,像素应该更积极吗?
我在这里做了一些错误的数学运算来检测绘制它的真实坐标吗?
非常感谢您的关注!
答案 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米的结果。