En esta práctica se implementarán todos los conocimientos adquiridos a lo largo del curso junto a un algoritmo de predicción de conflictos empleados en la aviación.
Práctica 6: Detección de intruso:
Implementación del algoritmo:
Para esta parte, se creará un objeto con los métodos necesarios para calcular las taus tal y como se pedía en clase después de leer el paper.
Importante tener en cuenta que para trabajar con el algoritmo, tenemos que usar un sistema cartesiano, mientras que la posición de los objetos se encuentra en formato WSG-84. Por lo que hay que realizar
un cambio de coordenadas.
import utm
import numpy as np
class avion:
def __init__(self, lat,lon,vx,vy) -> None:
self.lat = lat
self.lon = lon
self.x,self.y,basura,basura =utm.from_latlon(lat,lon)
print(self.x,self.y,basura,basura)
self.vx=vx
self.vy=vy
def tau(avion1,avion2):
s=np.array([avion2.x-avion1.x, avion2.y-avion1.y])
v=np.array([avion2.vx-avion1.vx,avion2.vy-avion1.vy])
tau =-(np.sum(s**2))/(np.dot(s,v))
return tau
def tau_mod(avion1,avion2,DMOD):
s=np.array([avion2.x-avion1.x, avion2.y-avion1.y])
v=np.array([avion2.vx-avion1.vx,avion2.vy-avion1.vy])
tau =(DMOD**2-np.sum(s**2))/(np.dot(s,v))
return tau
if __name__ == '__main__':
DMOD=0.2
avion1 = avion(lat=41.27479228277224,lon= 1.985268532366749, vx=1,vy=0)
avion2 = avion(lat=41.27547342864018, lon=1.9855681672713248, vx=-1,vy=0)
print('tau =', tau(avion1,avion2))
print('tau_mod =', tau_mod(avion1,avion2,DMOD=DMOD))
Test del algoritmo junto a dronekit:
Para realizar la desmostración, se ha planteado una ruta que va directamente hacia un obstáculo, el cual se ubica en la punta de la sombra producida por la farola. Por lo que es fácil tener una referencia visual.
Una vez comprobado el correcto funcionamiento del algoritmo, es hora de integrar este junto dronekit, para ello se diseña una función para comprobar el correcto funcionamiento entre módulos emulando los datos que ser recibirian de un canal MQTT.
import json
import numpy as np
import dronekit
from control import *
import paho.mqtt.client as mqtt
import signal
from threading import Thread
from TACAS import avion, tau_mod, tau
def avoidance(vehicle):
TAU =1
DMOD = 1
LocationGlobal = str(vehicle.location.global_frame)
LocationGlobal = LocationGlobal.replace(':',',')
LocationGlobal= LocationGlobal.replace('=', ',')
LocationGlobal=LocationGlobal.split(',')
lat = str(LocationGlobal[2])
lon = str(LocationGlobal[4])
alt = str(LocationGlobal[6])
v = np.array(vehicle.velocity).astype(np.float)
print(v)
avion1 = avion(lat,lon,1,1)
avion2 = avion(lat =41.274957,lon =1.984774 ,vx=0,vy=0)
tau = tau_mod(avion1,avion2,DMOD)
print(tau)
if tau<= TAU:
print('take action')
vehicle.mode = dronekit.VehicleMode("RTL")
conexion = 'tcp:127.0.0.1:5762'
vehicle = dronekit.connect(conexion, wait_ready=True, baud=115200)
while True:
avoidance(vehicle)
time.sleep(1)
Telemetría por MQTT:
Esta es la parte crucial de la práctica, pues es indispensable recibir los datos de otros vehículos/obstáculos para poder hacer los cálculos necesarios para evitar los conflictos. Por esto esta parte se encontrará desglosada.
Fichero JSON:
La Telemetría se mandará siguiendo un formato de codificación standard JSON, el cual permite trabajar los datos de forma estructurada y fácil mediante el uso de diccionarios. Se puede encontrar más información aquí, Entre otros datos, se manda un identificador único para saber quien ha sido el emisor del mensaje.
Aquí, se puede ver la función que genera la telemetría
def send_telemetry(vehicle):
broker = "test.mosquitto.org"
client =mqtt.Client("Sutton")
client.connect(broker)
topic = "excedida/telemetry"
while True:
LocationGlobal = str(vehicle.location.global_frame)
LocationGlobal = LocationGlobal.replace(':',',')
LocationGlobal= LocationGlobal.replace('=', ',')
LocationGlobal=LocationGlobal.split(',')
lat = str(LocationGlobal[2])
lon = str(LocationGlobal[4])
alt = str(LocationGlobal[6])
v = vehicle.velocity
data ={'ID':'Sutton','lat':lat, 'lon':lon, 'alt': alt, 'vx':v[0], 'vy':v[1], 'vz':v[2] }
client.publish(topic, json.dumps(data))
time.sleep(1)
Tratamiento de los mensajes:
Una vez recibido los mensajes, estos son procesado y se calcula el conflicto, tomando la medida pertinente.
Si la tau alcanza un valor límite el rover se pondrá en un return to launch para volver al origen y evitar la colisión
def listerner_telemetry(TAU,vehicle):
global avion1
global avion2
def command(client,userdata,cmd):
avion1 = None
avion2 = None
data = str(cmd.payload.decode('utf-8'))
data = json.loads(data)
if data['ID'] == 'Sutton':
avion1 = avion( data['lat'],data['lon'],data['vx'], data['vy'])
else:
avion2 = avion( data['lat'],data['lon'],data['vx'], data['vy'])
tau = 1e9
if avion1 != None and avion2 != None:
tau = tau_mod(avion1,avion2,DMOD)
print(tau)
if tau<= TAU:
print('take action')
vehicle.mode = dronekit.VehicleMode("RTL")
topic = "excedida/telemetry"
broker = "test.mosquitto.org"
client =mqtt.Client("Sutton")
client.connect(broker)
client.subscribe(topic)
client.on_message = command
client.loop_forever()
Emulación de tráfico de datos mediante MQTT:
Para emular el reporte de otras aeronaves se ha diseñado una función que publica la posición de un vehículo ficticio:
def emulate_conflict(lat =41.274957,lon =1.984774 ,alt=0):
broker = "test.mosquitto.org"
client =mqtt.Client("LuzDeGas")
client.connect(broker)
topic = "excedida/telemetry"
while True:
vx,vy,vz = 0,0,0
data ={'ID':'LuzDeGas','lat':lat, 'lon':lon, 'alt': alt, 'vx':vx, 'vy':vy, 'vz':vz }
client.publish(topic, json.dumps(data))
#print(json.dumps(data))
time.sleep(1)
Integración de las funciones anteriores: