Objectif: En général, le calcul de position à l'aide du Wi-Fi ou de Beacon vous permet de comprendre ce que vous faites dans les coulisses ~~.
Méthode: Je vais expliquer l'idée de base et la démontrer en utilisant du code Python.
environnement: MacOS Mojave 10.14.6, Python 3.7.4
Étape 1. Calculez la distance avec la ** courbe d'Okumura-Hata ** à partir de la force du signal reçu de l'émetteur et des informations de position du récepteur. Étape 2. Préparez un cercle centré sur la distance calculée comme le rayon et la position de chaque récepteur. Étape 3. Trouvez l'intersection des cercles avec ** Positionnement en trois points **. ** Coordonnées de l'intersection = Coordonnées de la position de l'émetteur **
Une image concrète du positionnement en trois points se trouve au bas de cette entrée. Si vous êtes intéressé, voyez d'abord cela.
Préparez les données de réponse correctes pour le calcul réel. Cette fois, nous avons ciblé les collines de Toramon où se trouve notre entreprise et les installations environnantes. La position spécifique est comme ça.
Maintenant que nous avons ces latitude / longitude Distance du théorème des trois carrés, Trouvez la puissance radio (théorique) de chaque récepteur à partir de la distance.
Cette fois, nous utilisons des environnements urbains, des villes de petite ou moyenne taille de Hata-model: Wikipedia.
# -*- coding: utf-8 -*-
import math
import numpy as np
import pandas as pd
import sympy.geometry as sg
# latitude 1 digree = 0.0090133729745762 km
# longitutde 1 degree = 0.010966404715491394
def eucl_dist(pointA, pointB):
return np.sqrt((pointA[0]-pointB[0])**2+(pointA[1]-pointB[1])**2)
# euclidean distance
def Oku_Hata(f, h_b, C_H, d):
Loss = (69.55 + 26.16*math.log10(f)
- 13.82*math.log10(h_b) - C_H
+ (44.9 - 6.55*math.log10(h_b))*math.log10(d))
return Loss
# Okumura_Hata Curve
def inv_Oku_Hata(f, h_b, C_H, Loss):
numerator = Loss - 69.55 - 26.16*math.log10(f) + 13.82*math.log10(h_b) + C_H
denominator = 44.9 - 6.55 * math.log10(h_b)
d = 10**(numerator/denominator)
return round(d, 10)
# Inversed Okumura_Hata Curve
# variables
f = 150 # frequency of transmissiton: Megahertz
h_b = 1 # height of base station antenna : meter
h_M = 1 # heigth of mobile station antenna ; meter
C_H =0.8 + (1.1 *math.log10(f) - 0.7) * h_M -1.56*math.log10(f)
d = 500
# Test whether or not the functions function?
euDist = eucl_dist([0,0],[3,4])
Loss = Oku_Hata(f, h_b, C_H, d)
d = inv_Oku_Hata(f, h_b, C_H, Loss)
print('euDist should be 5: ', euDist)
print('Loss from distance : ', Loss)
print('d should be 500: ', d) # Should be 500
Vérifier le résultat
euDist should be 5: 5.0 Loss from distance : 248.5613025107495 d should be 500: 500.0
La cérémonie semble bien se dérouler. Ensuite, calculez la distance à partir des informations de position réelles et convertissez-les en perte.
# Set of lattitude/ longitude each GeoData
tmitter = [35.6662344,139.7496597] # Transmitter from Torano-Mon
sensorLocation = {'S1':['GoodMorningCafe',35.6664959,139.7500406],
'S2':['LeParc',35.6666179,139.7479538],
'S3':['GrandSuite',35.6675194,139.7489692]}
# SensorLocation around Trano-Mon
# Compute distance (= radius) from the transmitter
r1 = eucl_dist(tmitter, sensorLocation['S1'][1:])
r2 = eucl_dist(tmitter, sensorLocation['S2'][1:])
r3 = eucl_dist(tmitter, sensorLocation['S3'][1:])
radii = [r1, r2, r3] # plural of radius
# Compute Loss
L1 = Oku_Hata(f, h_b, C_H, r1)
L2 = Oku_Hata(f, h_b, C_H, r2)
L3 = Oku_Hata(f, h_b, C_H, r3)
print('List of distance: ', radii)
print('List of Loss: ', L1, L2, L3)
résultat
List of distance: [0.0004620249560447818, 0.0017484756389397347, 0.0014587718293119327] List of Loss: -22.378972679965557 3.572964717331658 0.040582137429893805
Puisque la perte peut être calculée (à partir de la distance) Calculez la distance (à partir de la perte). ~~ Je le fais avec des données de réponse correctes, donc ça ne peut pas être aidé si je fais le tour. Ne me dites pas d'utiliser la distance depuis le début! ~~
d1 = inv_Oku_Hata(f, h_b, C_H, L1)
d2 = inv_Oku_Hata(f, h_b, C_H, L2)
d3 = inv_Oku_Hata(f, h_b, C_H, L3)
print('Computed Value: ', [d1, d2, d3]) # plural of radius
print('Original Value: ', radii)
Vérifier le résultat
Computed Value: [0.000462025, 0.0017484756, 0.0014587718] Original Value: [0.0004620249560447818, 0.0017484756389397347, 0.0014587718293119327]
Étant donné que la valeur est arrondie au milieu de la formule, le nombre de chiffres est différent, mais il semble qu'il puisse être calculé correctement.
code. J'ai utilisé sympy car il semble facile à utiliser. Qiita: L'intersection des cercles avec sympy
# Step2.
centers = [sg.Point(sensorLocation['S1'][2], sensorLocation['S1'][1]),
sg.Point(sensorLocation['S2'][2], sensorLocation['S2'][1]),
sg.Point(sensorLocation['S3'][2], sensorLocation['S3'][1])]
# x = longitude, y = latitude
circles = [sg.Circle(centers[0], radii[0]),
sg.Circle(centers[1], radii[1]),
sg.Circle(centers[2], radii[2])]
# define all three circles
print('List of centers (latitude/longitude) :', centers)
print('List of Circles :', circles)
résultat
Coordonnées du centre
List of centers (latitude/longitude) : [Point2D(698750203/5000000, 356664959/10000000), Point2D(698739769/5000000, 356666179/10000000), Point2D(349372423/2500000, 178337597/5000000)]
Informations sur le cercle. Le rayon a été ajouté. C'est une liste de coordonnées centrales et de rayons.
List of Circles : [Circle(Point2D(698750203/5000000, 356664959/10000000), 231012478022391/500000000000000000), Circle(Point2D(698739769/5000000, 356666179/10000000), 174847563893973/100000000000000000), Circle(Point2D(349372423/2500000, 178337597/5000000), 145877182931193/100000000000000000)]
code. Après tout j'utilise sympy. Il y a 3 cercles, mais 6 solutions peuvent être obtenues car les intersections sont calculées à 2 chacune. Par conséquent, la logique est d'extraire les intersections qui apparaissent trois fois sur les six solutions. Par conséquent, il arrondit et ignore l'erreur de calcul.
# Step3.
crossPoints12 = sg.intersection(circles[0], circles[1])
crossPoints23 = sg.intersection(circles[1], circles[2])
crossPoints31 = sg.intersection(circles[2], circles[0])
# Compute crosspoints for each two circles
crossPointsList = [
[float(crossPoints12[i].y),float(crossPoints12[i].x)] for i in [0,1]
] + [
[float(crossPoints23[i].y),float(crossPoints23[i].x)] for i in [0,1]
] + [
[float(crossPoints31[i].y),float(crossPoints31[i].x)] for i in [0,1]
]
crossPointsList = [[round(i[0],8), round(i[1],8)]for i in crossPointsList]
df = pd.DataFrame(crossPointsList).groupby([0, 1])[0].count()
print('Computed Value: ', df[df.values == max(df.values)].index[0])
print('Original Value: ', tmitter)
# print the most frequent set of lattitude-longitude
résultat
Computed Value: (35.6662344, 139.7496597) Original Value: [35.6662344, 139.7496597]
Il semble que la bonne réponse a été dérivée. Je suis heureux.
Si vous recherchez sur Google avec "positionnement en trois points", vous en verrez beaucoup, mais pour le moment, ce blog était la plus ancienne entrée que j'ai vue, donc je vais vous présenter le respect. Référence: J'aimerais pouvoir obtenir les coordonnées bidimensionnelles de l'iPhone avec RSSI d'iBeacon
Donc, quand je parle de la fin de l'histoire, je parle de blogs autres que les blogs ci-dessus, En pratique, ce code, en particulier la courbe de Hata, est inutile.
En ville, les objets sont dispersés et les ondes radio sont réfléchies de manière diffuse, de sorte que la propagation des ondes radio n'atteint pas le récepteur dans l'état idéal. Je n'ai pas l'intention de présenter l'histoire détaillée de ce domaine car cela dépasse le cadre des blogs techniques. Si vous voulez savoir, je pense que ce serait bien si vous pouviez Google ou nous rejoindre.
c'est tout.
~~ Je m'en fiche, mais j'ai l'impression que je vais me mordre la langue ~~