Python 中的半正矢公式(两个 GPS 点之间的方位角和距离)
问题
我想知道如何获取两个 GPS 点之间的距离和方位。
我研究了haversine距离。有人告诉我,我也可以使用相同的数据找到轴承。
一切工作正常,但轴承尚未完全正常工作。轴承输出负值,但应在 0 - 360 度之间。
设置的数据应使水平方位 96.021666666666666
是:
Start point: 53.32055555555556, -1.7297222222222221
Bearing: 96.02166666666666
Distance: 2 km
Destination point: 53.31861111111111, -1.6997222222222223
Final bearing: 96.04555555555555
这是我的新代码:
from math import *
Aaltitude = 2000
Oppsite = 20000
lat1 = 53.32055555555556
lat2 = 53.31861111111111
lon1 = -1.7297222222222221
lon2 = -1.6997222222222223
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
Base = 6371 * c
Bearing = atan2(cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1), sin(lon2-lon1)*cos(lat2))
Bearing = degrees(Bearing)
print ""
print ""
print "--------------------"
print "Horizontal Distance: "
print Base
print "--------------------"
print "Bearing: "
print Bearing
print "--------------------"
Base2 = Base * 1000
distance = Base * 2 + Oppsite * 2 / 2
Caltitude = Oppsite - Aaltitude
a = Oppsite/Base
b = atan(a)
c = degrees(b)
distance = distance / 1000
print "The degree of vertical angle is: "
print c
print "--------------------"
print "The distance between the Balloon GPS and the Antenna GPS is: "
print distance
print "--------------------"
Problem
I would like to know how to get the distance and bearing between two GPS points.
I have researched on the haversine distance. Someone told me that I could also find the bearing using the same data.
Everything is working fine, but the bearing doesn't quite work right yet. The bearing outputs negative, but it should be between 0 - 360 degrees.
The set data should make the horizontal bearing 96.02166666666666
and is:
Start point: 53.32055555555556, -1.7297222222222221
Bearing: 96.02166666666666
Distance: 2 km
Destination point: 53.31861111111111, -1.6997222222222223
Final bearing: 96.04555555555555
Here is my new code:
from math import *
Aaltitude = 2000
Oppsite = 20000
lat1 = 53.32055555555556
lat2 = 53.31861111111111
lon1 = -1.7297222222222221
lon2 = -1.6997222222222223
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
Base = 6371 * c
Bearing = atan2(cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1), sin(lon2-lon1)*cos(lat2))
Bearing = degrees(Bearing)
print ""
print ""
print "--------------------"
print "Horizontal Distance: "
print Base
print "--------------------"
print "Bearing: "
print Bearing
print "--------------------"
Base2 = Base * 1000
distance = Base * 2 + Oppsite * 2 / 2
Caltitude = Oppsite - Aaltitude
a = Oppsite/Base
b = atan(a)
c = degrees(b)
distance = distance / 1000
print "The degree of vertical angle is: "
print c
print "--------------------"
print "The distance between the Balloon GPS and the Antenna GPS is: "
print distance
print "--------------------"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
这是一个 Python 版本:
Here's a Python version:
这些答案大多数都是“绕”地球半径。如果您对照其他距离计算器(例如 geopy)检查这些功能,这些功能将被关闭。
这效果很好:
Most of these answers are "rounding" the radius of the earth. If you check these against other distance calculators (such as geopy), these functions will be off.
This works well:
还有一个矢量化实现,它允许使用 4 个 NumPy 数组而不是坐标标量值:
There is also a vectorized implementation, which allows to use 4 NumPy arrays instead of scalar values for coordinates:
您可以尝试 haversine 包:
示例代码:
输出:
You can try the haversine package:
Example code:
Output:
轴承计算不正确。您需要将输入交换到atan2。
这将为您提供正确的方位。
The bearing calculation is incorrect. You need to swap the inputs to atan2.
This will give you the correct bearing.
这是 @Michael Dunn 给出的半正矢公式的 NumPy 矢量化实现,给出了 10-50比大向量提高了几倍。
Here's a NumPy vectorized implementation of the Haversine Formula given by @Michael Dunn, gives a 10-50 times improvement over large vectors.
考虑到您的目标是测量两点之间的距离(由地理坐标表示),将留下以下三个选项:
半正矢公式
使用GeoPy 测地距离
使用GeoPy 大圆距离
选项 1
半正弦公式将做工作。然而,值得注意的是,这样做是将地球近似为一个球体,并且存在错误(请参阅此答案) - 因为地球不是一个球体。
为了使用半正矢公式,首先需要定义地球的半径。这本身可能会引起一些争议。考虑以下三个来源
NASA戈达德太空飞行中心: 6371公里
维基百科:6371 公里(3958.8 英里)
Google - 6371 公里
我将使用该值 < em>6371 公里作为地球半径的参考。
我们将利用
math
模块。半径之后,移动到坐标,首先将坐标转换为弧度,以便使用 数学的三角函数。对于这个,它导入
math.radians(x)< /code>
并按如下方式使用它们:
现在准备好应用半正弦公式。首先,将点 1 的经度减去点 2 的经度
,然后,这里将使用几个三角函数,更具体地说,
math.sin()
,math.cos()
和math.atan2()
。我们还将使用math.sqrt()
然后通过打印
d
来获取距离。因为它可能会有所帮助,所以让我们将所有内容收集在一个函数中(受到 Michael Dunn 的回答的启发)
选项 2
一种方法是使用 GeoPy 的距离,更具体地说,
测地线
。我们可以获得公里或英里的结果(来源 )
选项 3
将使用 GeoPy 的距离,更具体地说,
大圆
。
我们可以获得公里或英里的结果(来源 )
注释:
由于大圆距离通常使用半正弦公式计算 (正如 Willem Hendriks 指出的),选项 1 和 3 类似,但使用不同的半径。
地球,使用国际组织定义的平均地球半径
大地测量学和地球物理学联盟,约
6371.0087714150598 公里
6371.009 km
(对于WGS-84
),导致 up 错误大约
0.5%
[来源]。Considering that your goal is to measure the distance between two points (represented by geographic coordinates), will leave three options below:
Haversine formula
Using GeoPy geodesic distance
Using GeoPy great-circle distance
Option 1
The haversine formula will do the work. However, it is important to note that by doing that one is approximating the Earth as a sphere, and that has an error (see this answer) - as Earth is not a sphere.
In order to use the haversine formula, first of all, one needs to define the radius of the Earth. This, in itself, may lead to some controversy. Considering the following three sources
NASA's Goddard Space Flight Center: 6371 km
Wikipedia: 6371 km (3958.8 mi)
Google - 6371 km
I'll be using the value 6371 km as a reference to the radius of the Earth.
We will be leveraging
math
module.After the radius, one moves to the coordinates, and one starts by converting the coordinated into radians, in order to use math's trigonometric functions. For that one, it imports
math.radians(x)
and use them as follows:Now one is ready to apply the haversine formula. First, one subtracts the longitude of point 1 to the longitude of point 2
Then, and for here there are a couple of trigonometric functions that one is going to use, more specifically,
math.sin()
,math.cos()
, andmath.atan2()
. We will also be usingmath.sqrt()
Then one gets the distance by printing
d
.As it may help, let's gather everything in a function (inspired by Michael Dunn's answer)
Option 2
One is going to use GeoPy's distance, more specifically, the
geodesic
.We can obtain the results both on km, or miles (Source)
Option 3
One is going to use GeoPy's distance, more specifically, the
great-circle
.We can obtain the results both on km, or miles (Source)
Notes:
As the great-circle distance is often calculated using the Haversine formula (as Willem Hendriks noted), Option 1 and 3 are similar, but use a different radius.
the earth, using the mean earth radius as defined by the International
Union of Geodesy and Geophysics,
6371.0087714150598 kilometers
approx.6371.009 km
(forWGS-84
), resulting in an error of upto about
0.5%
[Source].您可以通过添加 360° 来解决负轴承问题。
不幸的是,这可能会导致正向轴承的轴承角度大于 360°。
这是模运算符的良好候选者,因此总而言之,您应该
在方法末尾添加该行。
You can solve the negative bearing problem by adding 360°.
Unfortunately, this might result in bearings larger than 360° for positive bearings.
This is a good candidate for the modulo operator, so all in all you should add the line
at the end of your method.
请参阅Vincenty 和 Great 之间的区别-圆距离计算。
这实际上提供了两种获得距离的方法。他们是哈弗辛和文森蒂。根据我的研究,我发现 Vincentys 的说法相对准确。还可以使用 import 语句来进行实现。
Refer to Difference between Vincenty and great-circle distance calculations.
This actually gives two ways of getting distance. They are haversine and Vincentys. From my research, I came to know that Vincentys is relatively accurate. Also use an import statement to make the implementation.
默认情况下,atan2 中的 Y 是第一个参数。这是文档。您需要切换输入以获得正确的方位角。
The Y in atan2 is, by default, the first parameter. Here is the documentation. You will need to switch your inputs to get the correct bearing angle.
这里有两个计算距离和方位的函数,基于之前消息中的代码和Compass Python 中两点之间的方位(为了清楚起见,我为两个函数添加了纬度、经度格式的地理点元组类型)。我测试了这两个功能,它们似乎工作正常。
Here are two functions to calculate distance and bearing, which are based on the code in previous messages and Compass bearing between two points in Python (I added a tuple type for geographical points in latitude, longitude format for both functions for clarity). I tested both functions, and they seemed to work right.
您可以在 Python 中使用以下实现,
您可以在 Haversine Formula 阅读更多相关信息
You can use the below implementation in Python
You can read more about it at Haversine Formula