4. Grafica radar – Python

Terminados los pasos anteriores, se usan los datos enviados por el arduino al puerto serial para realizar el grafico.

La gráfica se presenta en formato de coordenadas polares, que en la librería matplotlib se requieren en radianes. Antes de graficar se realiza una conversión.

Del ejemplo se  muestra que se crean tres elementos:

  • Pulso Punto, que marca el punto de la lectura «actual», la última recibida.
  • Pulso Linea, que traza la distancia entre el punto de origen y lectura «actual»
  • barrido, que grafica una linea de barrido del radar usando un grupo de puntos recibidos y almacenados en un vector.

Dado que los datos llegan «en vivo», la gráfica es animada, y se actualizan los datos de los tres elementos generando una nueva imagen en la función unatrama() de la animación. En la animación, se usa la opción ‘blit’ en la para actualizar solo los elementos del gráfico, manteniendo los ejes, títulos, etc sin cambios.

En las instrucciones en Python se usan números aleatorios para realizar la presentación.

Tarea

Integrar con la entrega de datos del experimento arduino. Observe que se debe sincronizar los tiempos de lectura del sensor, servo, datos Serial, gráfico, junto a los rangos de distancia del gráfico.

Use como referencia, Grafica animada:

http://blog.espol.edu.ec/edelros/grafica-animada-datos-serial/

Intrucciones en Python

# Grafica "en vivo" para actualizar datos
# recibidos por puerto serial
# Plantilla para proyecto, datos de prueba aleatorios
# http://blog.espol.edu.ec/edelros/category/arduino/radar-ultrasonido/
# Tarea: Actualizar los datos en la función una trama para ri,yi
#        Con los obtenidos desde el puerto Serial

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import random as rnd

# PARAMETROS DE LA GRAFICA
# angulo
avance = 20
angulo = avance
a = avance
b = 180-avance
# alcance del radar
alcance = 50

# Datos a graficar
xi = [avance]
yi = [0]

# GRAFICA figura
# tiempo entre tramas
retraso = 1000
figura = plt.figure()
grafica = figura.add_subplot(111, projection='polar')
grafica.set_xlim(0,np.pi)
grafica.set_ylim(0,alcance)
grafica.set_title('Radar de Ultradonido')

# Linea de barrido y ventana de datos a graficar
tamano = (180//avance)//2
# El gráfico usa radianes
ri = np.array(xi[-tamano:])/180*np.pi
di = yi[-tamano:]
barrido, = grafica.plot(ri, di, 'y')

# linea del pulso y puntoreferencia:
pulsox = [0,ri[-1]]
pulsoy = [0,di[-1]]
PulsoLinea, = grafica.plot(pulsox,pulsoy,'g')
PulsoPunto, = grafica.plot(ri[-1],yi[-1],'go')

# Nueva Trama
def unatrama(i, xi, yi,angulo,avance):

    # ---DATOS EJEMPLO|INICIO

    # Posición en ángulo
    if len(xi)>0:
        angulo = xi[-1]
    else:
        angulo = 0
    # Dirección de barrido
    direccion = 1
    if (len(xi)>=2):
        sentido = xi[-1]-xi[-2]
        direccion = np.sign(sentido)
        if angulo>=(180-avance) and sentido>0:
            direccion = -1
        if angulo<=avance and sentido<0:
            direccion = 1

    angulo = angulo + direccion*avance
   
    # alcance del radar
    alcance = 50
    # Recibe un dato nuevo| ejemplo usa aleatorio
    undato = int(rnd.random()*alcance)+1
    # ---DATOS EJEMPLO|INICIO

    # actualiza datos xi, yi
    xi.append(angulo) 
    yi.append(undato)# numero del dato ejemplo

    # ventana de datos a graficar
    tamano = (180//avance)//2

    # Linea de radar, el gráfico usa radianes
    ri = np.array(xi[-tamano:])/180*np.pi
    di = yi[-tamano:]
    barrido.set_xdata(ri)
    barrido.set_ydata(di)
    
    # Linea y punto del Pulso
    pulsox = [0,ri[-1]]
    pulsoy = [0,yi[-1]]
    
    PulsoLinea.set_xdata(pulsox)
    PulsoLinea.set_ydata(pulsoy)

    PulsoPunto.set_xdata(pulsox[1])
    PulsoPunto.set_ydata(pulsoy[1])  

    # Presenta valores últimos valores en pantalla
    print(xi[-1],yi[-1])

    # Si los datos son más de 1000
    # Elimina el más antiguo del historial
    if len(xi)>1000:
        xi.pop(0)
        yi.pop(0)
    
    return()

# Animación
ani = animation.FuncAnimation(figura,
                              unatrama,
                              fargs=(xi, yi,angulo,avance),
                              interval=retraso,
                              blit=True)

plt.show()

Referencias

https://matplotlib.org/examples/pylab_examples/polar_demo.html

https://learn.sparkfun.com/tutorials/graph-sensor-data-with-python-and-matplotlib/speeding-up-the-plot-animation