Localización en interiores usando redes WiFi

Ya hemos visto que usar la distancia al emisor para posicionarte dentro de casa es muy difícil, al menos sin usar hardware especializado. ¿Nos hemos quedado sin opciones?. Somos gente ingeniosa, no nos quedamos sin opciones. Si no podemos usar la distancia por la gran variación que tiene la potencia de la señal en interiores, le daremos la vuelta al problema y lo usaremos como ventaja. Si a la gran variación que hay en la potencia de la señal le sumamos la gran cantidad de nodos WiFi que hay alrededor nuestro, resulta muy poco probable que en dos puntos que no estén muy próximos se den los mismos valores para todas las redes.

Vamos a empezar por la idea básica y luego desarrollaremos los distintos problemas que surgen en la vida real.

Primero vamos a movernos por nuestra casa midiendo la potencia de las redes WiFi que se reciben en distintos puntos que consideramos interesantes para localizarnos. Obtendremos una lista de tuplas {SSID, potencia} para cada punto.

Una vez tengamos esa base de datos creada vamos a tratar de saber lo «cerca» que estamos de esos puntos sabiendo solo la potencia de los wifi que nos rodean. En este caso «cerca» no se refiere a distancia física en metros si no a lo parecidas que son las mediciones en dos puntos. Aunque no tenga que ver con la distancia física a este concepto también se le llama distancia.

Para medir esta distancia es fundamental saber que valor o valores vamos a usar, en este caso la potencia de la señal del WiFi. Vamos a compararla con las potencias almacenadas en nuestras mediciones anteriores. Para ello tomaremos las potencias medidas en los nodos con el mismo SSID y las compararemos, sumando luego todas para saber como de «próximos» están esos dos puntos.

Siendo Pi[ssid] la potencia en la base de datos para el nodo con ese SSID en el punto i y Pm[ssid] para la potencia medida de ese mismo nodo la distancia seria:

Dist(Pi) = ∑ √ (Pi[ssid] – Pm[ssid])²

O una forma menos exacta pero también computacionalmente menos costosa (y que a mi me a servido perfectamente)

Dist(Pi) = ∑ ABS(Pi[ssid] – Pm[ssid])

Siendo ABS la función que calcula el valor absoluto.

Que la i no despiste, en ambas formulas el sumatorio se refiere a sumar la diferencias de los distintos SSID medidos de cada punto.

Podemos determinar de que punto estamos más cerca comparando estas distancias y quedándonos con aquel punto Pi cuyo valor sea menor.

Para aplicar esta idea dividí mi casa (realmente solo dos habitaciones contiguas y un trozo de pasillo para probar) en una matriz de cuadrados de un metro de lado y establecí comos puntos de referencia el centro (a ojo) de cada cuadrado.

¿Funciono bien? La sorpresa es que, tras corregir problemas de los que hablo más adelantem mucho mejor de lo que esperaba. Buscando los puntos más cercanos me resultaba fácil saber donde estaba. No siempre me daba como más cercano el punto del que más cerca estaba pero nunca se fue muy lejos, así que podía saber mi posición con bastante precisión.

Problemas

Desgraciadamente de la teoría a la practica suele haber un camino lleno de baches. Por lo que siempre surgen problemas para aplicar la teoría tal cual y que hay que resolver.

Nodos que aparecen y desaparecen

Si los nodos WiFi que usas como referencia están siempre encendidos el hecho de que un nodo no esté entre tus mediciones indica que potencia es 0 y es un gran indicador de donde estamos. Pero si usas los WiFis de tus vecinos el que se apaguen a lo largo del día es algo más habitual de lo que parece. Por lo que tenemos nodos que aparecen y desaparecen. Así que si un nodo no esta entre tus mediciones no se puede considerar que su potencia es 0 (aunque lo sea en ese momento) ya que puedes estar falseando los resultados. Mi experiencia es que si no tienes medición de un nodo lo descartes y no lo tengas en cuenta en tus cálculos.

Ruido en las mediciones

Los valores de potencia pueden variar muchísimo al realizar una medición, mi consejo es que realices varias medidas (yo uso 3) y te quedes con la mediana o la moda de las mismas. Es muy importante sobretodo que realices esto al generar la base de datos de los puntos de referencia.

Otro problema es que no todas los nodos se ven sometidos a las mismas variaciones, contra menor potencia tengan en ese punto más propensas son a sufrir variaciones y más amplias son estas. En algunos casos resulta conveniente fijar un umbral mínimo de potencia para tener en cuenta ese nodo.

Variación de las medidas usando distintos aparatos.

Es recomendable usar el mismo «aparato» para generar la base de datos de puntos que el que luego se va a intentar localizar. Las medidas entre mi portátil, mi smartphone y mi placa Node MCU eran suficientemente distintas como para causar errores si intentaba comprar unas con otras

Trilateralización

Tras que medir la distancia al emisor no diera el resultado deseado pensé en no escribir esta entrada, pero como puede ser útil y ya la tenia medio escrita he decidido terminarla.

Ya hemos visto cómo calcular (más o menos) la distancia a un emisor. Si conocemos la situación del emisor podemos situarnos en algún punto de una circunferencia de radio r1 (r1 es igual a la distancia al emisor). Si añadiéramos un segundo emisor de coordenadas conocidas y al que calculamos la distancia r2. Esto nos sitúa en una segunda circunferencia que corta a la primera en dos puntos. Ahora ya sabemos que estamos situados en uno de esos dos puntos. Para saber en cual exactamente necesitamos un tercer emisor cuya posición conozcamos y del que podamos calcular la distancia r3. Esta tercera circunferencia coincidirá con las otras dos en un solo punto. En la imagen se ve mejor

Trilateration.svg
De Braindrain0000 de la Wikipedia en inglés, CC BY-SA 3.0, Enlace

Ahora toca ponerlo todo en lenguaje matemático. En lugar de usar circunferencias vamos a usar esferas, los cálculos son los mismo y nos permite no tener los tres emisores y el receptor en el mismo plano. La ecuación de una esfera cuyo centro está en las coordenadas (a,b,c) es:

(x ─ a) 2 + (y ─ b) 2 + (z ─ c) 2= r2

Esta ecuación representa a todos los puntos de la súperficie de una esfera. Cómo tenemos tres esferas que coinciden en un punto de sus superficies hay que buscar un punto (x,y,z) que cumpla las ecuaciones de las tres esferas.

Esfera1, vamos a ser amables con nosotros mismo y vamos a colocar esta esfera en el origen de coordenadas (0,0,0) por lo que su ecuación es:

x 2 + y 2 + z 2 = r12

Esfera2, también por simplificar nos la vida, colocamos el centro de esta esfera en línea con la anterior en las coordenadas (d,0,0). Su ecuación es:

(x – d)2 + y 2 + z 2 = r22

La tercer esfera la colocamos con el centro en el mismo plano pero con ambas coordenadas distintas.

(x – i)2 + (y – j) 2 + z 2 = r3

En el articulo de la wikipedia esta la resolución completa de las ecuaciones paso a paso, yo salto a la conclusión:

x = (r1 2 – r2 2 + d 2 ) / 2d

y = (r1 2 – r3 2 + i 2 + j 2) / 2j + (x * i / j)

z = √(r1 x 2 – y 2 )

Con estos cálculos ya tienes localizado el punto exacto. Desgraciadamente en la vida real las mediciones no suelen ser tan exactas por eso la mejor solución es detectar donde cortan dos circunferencias (por ejemplo la 1 con la 2 y la 1 con la 3) Buscar los puntos mas cercano y tomar el punto medo entre ambos, teniendo en cuenta que es una aproximación y que no será el punto exacto.

Medir distancia al emisor WiFi.

La idea es sencilla, mides la potencia de la señal de varias estaciones cuya posición conoces, con la potencia calculas la distancia a cada estación y a partir de ahí con geometría básica calculas tu posición. Parece fácil, hasta que lo intentas y vas viendo como todo se complica.

Como estación vamos a usar un emisor WiFi, eso nos permitirá realizar pruebas fácilmente ya que podemos usar cualquier router WiFi como estación y como receptor cualquier móvil. Vamos a empezar por lo mas sencillo, medir la distancia a un solo nodo cuya localización conocemos. En nuestro receptor podemos ver la potencia. ¿Como convertimos la potencia en distancia?. Las malas noticias es que no es lineal. Las buenas es que hay fórmula (Free-space path loss) para hacerlo de manera aproximada

dB = 20log10(d) + 20log10(f) + K

K varia segun las unidades de medida de la distancia d y la frecuencia f, siendo:

  • K = 92.45 si d está en km y f en Ghz
  • K = -87.55 si d está en m y f en Khz
  • K = -27.55 si d está en m y f en Mhz
  • K = 32.45 si d está en km y f en Mhz

Lo que nos interesa son metros y Mhz. Como frecuencia de la seña WiFi se puede usar siempre 2400 Mhz sin temer cometer un gran error (aunque ya hay algunas redes que operan a otras frecuencias como 5 Ghz)

Aunque no es del todo exacta en muchas aplicaciones usan directamente esta formula para calcular la distancia. En el receptor podemos conocer  la atenuación (dB), la frecuencia (f) y la constante (K). Ahora podemos resolver la distancia (d).

dB – (20log10(f) + K) = 20log10(d)

Cómo ni f ni K van a variar en nuestro caso vamos a remplazarlos por una constante C

dB – C = 20log10(d)

Despejando d

d = 10^((dB – C)/20)

Si queremos ser mas exactos no basta con leer la potencia de señal que se recibe en el receptor ya que la formula esta expresada en decibelios (dB) y la potencia de la señal WiFi nos la devuelve el sistema en decibelios-miliwatio (dBm). Que aunque aparentan ser lo mismo no lo son. Los dB son una medida relativa de potencia entre dos valores (en este caso serian la potencia de emisión del nodo WiFi y la potencia percibida en el receptor). Sin embargo los dBm indican un valor de potencia expresado en relación a 1 mW. Que para los que no estamos acostumbrados a este campo todo esto nos suena a chino y lo único que queremos saber es: ¿Como se convierte de una unidad a la otra?. Pues no es tan sencillo porque cada unidad mide cosas diferentes. Voy a tratar de explicarlo para este caso y perdonarme si meto mucho la pata, ya os digo que no es un tema que domine. Los dB serian la diferencia de potencia entre la señal original y el punto donde estas recibiéndola y se calcula como:

dB = 10log10(P/P0)

Siendo P la potencia medida y P0 la emitida o de referencia. Necesitamos obtener esas dos potencias. Para ello podemos usar los dBm, que son los dB medidos tomando como potencia de referencia 1mW por lo que la formula queda:

dBm = 10 log10(P/1mW)

Podemos calcular P en mW fácilmente.

P = 10 ^ (dBm/10)

¿Pero de donde sacamos P0?. Los que esperéis complicados cálculos siento decepcionaros. La forma de calcular P0 (de forma aproximada) es acercarse lo más posible al emisor y medir la potencia en dBm, despejar la formula anterior y usar ese valor como P0.

Con todo esto podemos calcular el valor en dB de la atenuación de la señal. Así que ahora podemos volver a la primera formula para calcular la distancia.

En javascript

function dBm2dB(dBm0, dBm){
  var P0 = Math.pow(10, dBm0/10);
  var P = Math.pow(10, dBm/10);
  var dB = 10 * Math.log10(P/P0);
  return dB;
}

function fspl(dB,f,K){
  var logF = 20*Math.log10(f) + K;
  var d = Math.pow(10, (Math.abs(dB) - logF)/20);
  return d;
}

//ejmeplo
fspl(dBm2dB(-29, -58), 2400, -27.55)*10;

¿Que tal resultado da? Pues por alguna extraña metedura de pata que no logro localizar necesito multiplicar el resultado por 100 para que las cifras tengan sentido. La aproximación es buena pero no lo suficiente, incluso sin moverse los valores de la señal varían mucho. Como sistema de localización, la potencia de la señal WiFi deja mucho que desear