Wi-Fi位置三角剖分 [英] Wi-Fi position triangulation
问题描述
考虑此地图:
我需要了解Wi-Fi三角测量的基本原理.上图中描绘了该场景.为了实施Wi-Fi三角测量,我至少需要三个Wi-Fi热点及其位置.设置:
-
为简单起见,假设我有一个 1平方公里乘1平方公里的区域,并且该区域有三个Wi-Fi热点.坐标系如下:正方形区域的一个角为(0,0,0),对角最远的角将具有坐标(1,1,1).所有位置确定都将仅相对于此坐标系完成(为简单起见,我不希望使用全局xyz坐标).在其中,我有三个Wi-Fi热点,分别位于(x1,y1,z1),(x2,y2,z2),(x3,y3,z3).
-
我们有一个设备能够接收Wi-Fi信号并计算位置(x,y,z)的信号强度的人.该设备可以是手机,平板电脑等.
问题:当您现在有了以下输入时,动态地计算人员的位置(x,y,z):
-
从每个Wi-Fi热点接收的信号的信号强度
-
以前存储在变量或数据库中的Wi-Fi热点的坐标.
第一个问题:如何根据上述输入来计算排名?我假设信号强度与到路由器的距离成正比,但是确切的关系是什么? Skyhook 如何做到如此精确?
第二个问题:我相信以上输入已经足够.还有其他需要吗?
这很容易.这只是一些基本的数学.将其分为两部分:
- 查找水平位置(无高度).
要找到您的位置,您需要三点,但第二秒只需要关注两点即可.通过使用两个点,您可以自己创建一个三角形,并根据两个点之间的信号强度找到位置.这将找出您在两个路由器之间的位置.例如,如果您位于路由器3和4之间,并且与3相比,信号强度为-89,而与4相比,信号强度为-54,那么您知道自己比3更接近3.如果您将距离与信号强度进行比较,则可以非常准确地了解路由器3和4之间的位置.剩下的问题就是确定您在3和4之间处于哪一侧.,因为您可能在路由器的上方或下方具有相同的信号强度值(-89,-54)(请参见图表)
6你可能会在这里3 -------------------------- 4你也可以在这里5
然后只是找到另一个路由器,并注意您的信号强度.您只需看一下5个和6个路由器之间的信号强度关系即可(图中)轻松地确定要站在哪一侧.
- 您可以用高度做同样的事情.
要完成上述所有操作,您实际上仅需要距离与信号强度之间的近似值,以及路由器之间的距离即可.根据我的测试(我编写了自己的Wi-Fi三角测量代码),跨移动设备的信号强度非常均匀,因此一台设备应具有与其附近设备相同的结果.
Skyhook 我认为这是通过GPS定位(可能是硬编码的),或与此基本相同的原理.Skyhook是Apple唯一为此批准的服务,因此Apple基本上做了同样的事情,然后确保其他应用程序无法使用它(任何使用受限制的应用程序商店).
如何查找距离
您需要做一些简单的近似.根据您的环境,这些近似值可能不尽相同,因此-89英尺(27米)可能意味着您距离路由器3 15英尺(4.5 m),但是距路由器4则-89英尺(27 m)可能意味着您距离13英尺(4 m).无论您做什么,这都不会100%准确,但这没关系,因为您可以确定在5英尺(1.5米)以内.
因此,您要做的是找到一堆要点,从路由器3的-89处获得读数,然后记下距离.然后,您取一个平均值,然后使用该平均值将其放到数据库中(这表示从路由器3到-89时,您只有15英尺(4.5 m)).然后,您对其他值(例如-50或其他值)执行此操作,然后记下您的值并找到平均值.现在,如果-89表示您距离4.5毫米(15英尺),而-50表示您距离4.5毫米(25英尺)(仅举一个例子),那么当您距-75的距离约为路由器3,除非您想手动获得-75的近似值.对于成千上万的值而言,这将很麻烦,但是您必须进行实验,以查看尽可能少的数据点所能达到的精度.
通过意识到信号强度是对数的,您可以在两个信号强度平均值之间进行近似估算,因此您可以估计由于-89为15英尺(4.5 m),因此-75将是对数的(以10为底数或以2为底数,我可以不记得了,但是我倾向于以10为底的底数,距-89的距离是14/100.
要求代码
我在某个地方有代码,但是那是几年前的事,所以我必须仔细研究很多东西才能找到它.我认为从概念上讲,无需代码即可轻松复制.我为要测试的android设备花了大约50行Java代码.
基本上,我带了一个Android手机,并创建了一个应用程序,该应用程序使我可以随时显示已连接的Wi-Fi设备的当前ID,其信号强度,附近的其他Wi-Fi ID及其信号强度以及GPS地点.所有这些都可以通过Android的API访问.我认为您需要使用API 4或更高版本的Android设备.就像三,四年前一样,所以我只是把它从我记得的东西中剔除掉.
GPS位置部分是使物理强度和Wi-Fi强度之间的映射更容易,而不是必须以其他方式创建我的设施的蓝图,我可以让Google地图同时为我做这件事因为我可以在创建距离图的同时基本上覆盖他们的地图和GPS坐标.不过,您仍然需要一个深度图来绘制楼层平面图,我们可以很容易地通过发现您是否位于两个路由器之间来手动完成此操作.
我们知道同一楼层的Wi-Fi集线器的信号强度最强,然后可以通过确保到不同楼层的Wi-Fi集线器的信号较弱来进行双重检查.该深度图实质上是Wi-Fi集线器及其各自楼层的列表.
我们不需要它们的位置,因为我们可以使信号强度最适合我们在设施周围走动并将信号强度捕获到某些集线器时所捕获的GPS位置.这是一些简单的数学运算.因此,对于2D平面位置,从顶部向下看,我们有一堆这样的对象:
BestFitObject {元组GPSLocation;列表<元组< Wifi设备,signedInt>>WifiReadings;//WifiDeviceName(通过UUID或其他方式),在获取bestFit读数时将其与signalStrength组合}WifiDevice {UUID ID;//认为字符串应该可以正常工作,可能是包含UUID的内部类型,这样会更好.int floorNumber;元组GPSLocation;//并非完全必要,尽管可以提供更好的准确性}
然后,当我们对客户端设备执行ping操作并希望最适合该设备时,它会返回这样的对象:
ClientPosition {列表<元组< UUID,signedIt>附近的信号;//Wi-Fi设备的UUID的元组,以及在ping期间获取的信号强度.}
然后,我们可以轻松地将ClientPosition最佳地拟合到我们使用上述两个对象创建的2D地图.
以上内容非常简单,我认为深度图甚至更简单.
理想情况下,您想要尝试使用包含多种不同无线技术的多种不同设备(某些设备,某些b设备,n,g等),以获得更准确的结果.但是我发现准确度并不重要,您将在5英尺(1.5 m)左右的范围内.这足以满足我的需求.理想情况下,所有Wi-Fi集线器都是相同的型号,它们通常位于大型设施/公司中,但是即使那样,这也没什么大不了的.变异是如此之小,如果您不需要疯狂的准确性,那就没关系了.
Consider this map:
I need to understand how Wi-Fi triangulation basically works. The scene is portrayed in the above diagram. In order to implement Wi-Fi triangulation, I need a minimum of three Wi-Fi hotspots and their positions. The setup:
For simplicity, let's assume I have a 1 sq-Km by 1 sq-Km area, and I have three Wi-Fi hotspots in this area. The coordinate system is as follows: One corner of the square area is (0,0,0), and the diagonally furthest corner will have coordinates (1,1,1). All position determination is to be done relative to this coordinate system alone (for simplicity, I don't want global xyz coordinates). Within this, I have three Wi-Fi hotspots at (x1,y1,z1) , (x2,y2,z2), (x3,y3,z3).
We have a person with a device capable of receiving Wi-Fi signals and calculating the strength of the signal at position (x,y,z). The device could be a phone, a tablet, etc.
The problem: Calculate position (x,y,z) of the person dynamically, as they move around when you now have the following inputs:
The signal strength of signals received from each of the Wi-Fi hotspots
Coordinates of the Wi-Fi hotspots previously-stored in variables or a database.
First Question: How do I calculate position from the above inputs? I assume signal strength is directly proportional to the distance from the router, but what's the exact relation? How does Skyhook do this so accurately?
Second Question: I believe the above inputs are sufficient. Is there anything else required?
This is pretty easy. It's just some basic maths. Break it down into two parts:
- Finding your horizontal location (no height).
To find your location, you need three points, but just focus on two points for a second. By using two points, you can create a triangle with yourself, and find your location based on your signal strength between two points. This will find out where you are in between two routers. For instance, if you're in between routers 3 and 4, and your signal strength in comparison to 3 is -89 and your signal strength to 4 is -54, you know that you're closer to 3 than you are to 4. If you do an approximation of distance vs signal strength, you can come up with a pretty accurate read of where you are in between routers 3 and 4. The problem left over then, is determining which side you're on in between 3 and 4, since you could have the same signal strength values (-89, -54) either above or below the routers (look at diagram)
6
You could be here
3--------------------------4
You could also be here
5
Then just find another router, and notice your signal strength. You should be able to determine which side you're on pretty easily just by taking a look at signal strength relationships between 5 and 6 routers (in the diagram).
- You can do the same thing with height.
To do all of the above, you really only need an approximation of distance vs signal strength, and the distances between the routers. From my testing (I wrote my own Wi-Fi triangulation code), the signal strength is pretty uniform across mobile devices, so one device should have the same results as the device next to it.
Skyhook does this I think either through GPS positioning (it might be hard coded in), or basically the same principle as this. Skyhook is the only service that is Apple approved for this, so Apple basically did this same thing and then made sure other apps couldn't use it (any iPhone app that uses the restricted 802.11 library that contains the functions in order to do this will be denied from the App Store).
How to find distance:
You need to do some simple approximations. These approximations will not be all the same depending on your environment, so -89 feet (27 m) might mean you're 15 feet (4.5 m) away from Router 3, but -89 feet (27 m) from router 4 might mean you're 13 feet (4 m) away. No matter what you do, this isn't going to be 100 percent accurate, but that's okay, because you can get within 5 feet (1.5 m) for sure.
So what you do is you find a bunch of points where you get a reading from -89 from router 3, and you jot down what your distance was. Then, you take an average, and you use this average to put down in your database (which says when you're -89 from router 3, you're 15 feet (4.5 m)). You then do this for other values, like -50 or whatever, and you jot down your values and find an average. Now, if -89 means you're 15 feet (4.5 m) away, and -50 means you're 25 feet (4.5 m) away (just an example), you have to approximate your distance when you're -75 from router 3 unless you want to go get an approximation by hand for -75. This would be cumbersome for tons of values, but you'll have to experiment to see how accurate you can be with as few data points as you can get.
You can approximate between two signal strength averages by realizing that signal strength is logarithmic, so you can estimate that since -89 is 15 feet (4.5 m), then -75 would be logarithmically (base 10 or base 2, I can't remember, but I'm leaning towards base 10) further away than -89 by a factor of 14/100.
Asking for code
I have the code somewhere, but it was a couple years ago so I'd have to dig through a lot of stuff to find it. I think conceptually, it should be easy to replicate without code. It took me about 50 lines of Java code for the android devices I was testing.
Essentially I took an android phone and created an application that allows me to at any moment display the current ID of the connected Wi-Fi device, its signal strength, other nearby Wi-Fi ID's and their signal strength, and then GPS location. This is all accessible through Android's API. I think you need an Android device on API 4 or higher or something. This was like three or four years ago, so I'm just throwing this out from what I remember.
The GPS location part was to make the mapping between physical and Wi-Fi strength easier, rather than having to create a blueprint map of my facility in some other way, I could just have google maps do it for me at the same time since I can overlay their map and the GPS coordinates essentially, while creating the distance map. You'd still need a depth map to map floor levels though, which we can do by hand pretty easily by finding if you're in the middle of two routers.
We know that signal strength is strongest to Wi-Fi hubs on the same floor, and then can double check by making sure you have weaker signals to Wi-Fi hubs on different floors. This depth map is essentially a list of Wi-Fi hubs, and their respective floors.
We do not need their positions, since we can best fit the signal strength to the GPS locations we grabbed when walking around the facility and grabbing the signal strength to certain hubs. This is some simple math. So for 2D plane position, looking down from the top, we have a bunch objects like such:
BestFitObject{
Tuple<long, long> GPSLocation;
List<Tuple<WifiDevice, signedInt>> WifiReadings; //WifiDeviceName(through UUID or some other way), tupled with the signalStrength when that bestFit reading was taken
}
WifiDevice{
UUID ID; // Think a string should work fine, might be an internal type that encompasses UUID which would be better.
int floorNumber;
Tuple<long, long> GPSLocation; // Not entirely necessary, could provide better accuracy though
}
And then when we ping the client device and want to best fit it, it returns an object like this:
ClientPosition{
List<Tuple<UUID, signedIt> NearbySignals; // Tuple of the UUID of the Wi-Fi device and the signal strength taken during the time of the ping.
}
Then we can easily best fit our ClientPosition to the 2D map that we created with the above two objects.
The above is pretty simple, and the depth map is even simpler in my opinion.
Ideally, you'd want to try and hit a couple different devices that encompass a couple different wireless techs (some a devices, some b devices, n, g etc) just to get more accurate results. What I found though, was that accuracy isn't that big of a deal, and you'll be within 5 feet (1.5 m) or so. That was accurate enough for my needs. Ideally, all the Wi-Fi hubs are the same model, and they usually are in large facilities/companies, but even then, it's not that big of a deal. The variability is so small, and if you don't need crazy accuracy, it won't matter.
这篇关于Wi-Fi位置三角剖分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!