Documente Academic
Documente Profesional
Documente Cultură
Modificar un automóvil a control remoto para que realice tres tareas: conducción autónoma
en la vía, detección señal de stop y del semáforo, y prevención de colisión frontal.
Diseño de sistemas
El sistema consta de tres subsistemas: unidad de entrada (cámara, sensor ultrasónico), unidad
de procesamiento (computadora) y unidad de control de cabina de control Remoto.
Unidad de entrada
Unidad de procesamiento
Servidor TCP
Red neuronal
Una de las ventajas del uso de redes neuronales es que una vez que la red está capacitada,
solo necesita cargar parámetros entrenados posteriormente, por lo que la predicción puede
ser muy rápida. Solo la mitad inferior de la imagen de entrada se usa con fines de
entrenamiento y predicción. Hay 38,400 nodos (320 × 120) en la capa de entrada y 32 nodos
en la capa oculta. El número de nodos en la capa oculta se elige bastante arbitrario. Hay cuatro
nodos en la capa de salida donde cada nodo corresponde a las instrucciones de control de
dirección: izquierda, derecha, adelante y atrás respectivamente (aunque el reverso no se usa
en ningún lugar de este proyecto, aún se incluye en la capa de salida).
Detección de objetos
Este proyecto adaptó el enfoque basado en formas y utilizó clasificadores en cascada basados
en características de Haar para la detección de objetos. Dado que cada objeto requiere su
propio clasificador y sigue el mismo proceso en el entrenamiento y la detección, este proyecto
solo se centró en la detección de señales de stop y semáforos.
Para reconocer diferentes estados del semáforo (rojo, verde), se necesita algo de
procesamiento de imágenes más allá de la detección. El siguiente diagrama de flujo resume el
proceso de reconocimiento del semáforo.
Medición de distancia
Raspberry Pi solo puede admitir un módulo de cámara pi. El uso de dos cámaras web USB
aportará un peso adicional al automóvil RC y también parece poco práctico. Por lo tanto, se
elige el método de visión monocular.
El auto de CR usado en este proyecto tiene un controlador tipo encendido / apagado. Cuando
se presiona un botón, la resistencia entre el pin del chip correspondiente y la tierra es cero.
Por lo tanto, una placa Arduino se usa para simular acciones de presionar un botón. Se eligen
cuatro pines Arduino para conectar cuatro pines de chip en el controlador, que corresponden
respectivamente a las acciones hacia adelante, hacia atrás, hacia la izquierda y hacia la
derecha. Los pines Arduino que envían la señal BAJA indican la conexión a tierra de los pines
del chip del controlador; por otro lado, el envío de la señal HIGH indica que la resistencia entre
los pines del chip y la tierra no cambia. Arduino está conectado a la computadora a través de
USB. La computadora emite comandos a Arduino utilizando la interfaz serie, y luego el Arduino
lee los comandos y escribe señales BAJAS o ALTAS, simulando acciones de presionar un botón
para conducir el auto RC.
Resultados
La predicción en las muestras de prueba arroja una precisión del 85% en comparación con la
precisión del 96% que devuelve la muestra de entrenamiento. En la situación de conducción
real, las predicciones se generan aproximadamente 10 veces por segundo (velocidad de
transmisión de aproximadamente 10 cuadros / s).
Las características de Haar por naturaleza son sensibles a la rotación. En este proyecto, sin
embargo, la rotación no es una preocupación, ya que tanto la señal de pare y el semáforo son
objetos fijos, que también es un caso general en el entorno del mundo real.
Para el aspecto de medición de distancia, el sensor ultrasónico solo se usa para determinar la
distancia a un obstáculo en frente del automóvil RC y proporciona resultados precisos al tomar
en cuenta el ángulo de detección y la condición de la superficie. Por otro lado, la cámara Pi
proporciona resultados de medición "lo suficientemente buenos". De hecho, siempre que
sepamos el número correspondiente a la distancia real, sabemos cuándo detener el automóvil
RC.
En general, el auto RC podría navegar con éxito en la pista con la capacidad de evitar la colisión
frontal, y responder en consecuencia a la señal de stop y al semáforo.
Recopilación de datos
1. Datos de video: un video no es más que una serie de fotos. Uso OpenCV para
representar cada cuadro como una matriz de números, donde cada número
representa un píxel. Si desea video en blanco y negro, OpenCV le dará una
matriz bidimensional que consta de la altura y el ancho de un cuadro. Si decides
que quieres un video en color, entonces OpenCV te dará una matriz
tridimensional que consta no solo de alto y ancho sino también de profundidad
de color: rojo, verde y azul. El modelo de aprendizaje automático utilizará los
píxeles de la matriz como predictores.
2. Datos de comando: los comandos le dicen a los motores qué hacer y
representan la variable objetivo. El modelo intentará aprender qué comandos
enviar al motor según el video que ve. Fui por simplicidad, así que solo definí
tres tipos de comandos: izquierda, derecha y adelante. Esto hace que conducir
un problema de clasificación multinomial. La desventaja de tener solo tres
comandos es que las instrucciones pueden ser bastante crudas. No hay
distinción entre un giro amplio y un giro brusco.
# Run ffmpeg. I have no idea how this command works since I copy-and-pasted it from some website off
of Google
sudo ffserver -f /etc/ff.conf_original & ffmpeg -v quiet -r 5 -s 320x240 -f video4linux2 -i /dev/video0
http://localhost/webcam.ffm
En este punto, el video en tiempo real debe estar disponible en la siguiente URL. Sin
embargo, no podrá ver el video en bruto desde su navegador; su navegador intentará
sin parar descargar el archivo de transmisión. Tenga en cuenta que la IP
probablemente sea diferente para usted.
http://ryanzotti.local/webcam.mjpeg
Inicie el servidor web API. Inicie sesión en Raspberry Pi en otra pestaña. Clona este
repositorio en el Pi y muévete a la carpeta. Luego, inicie el servidor que aceptará
comandos remotos para conducir el automóvil (consulte el drive_api.pysiguiente
comando).
La velocidad de conducción podría ser un parámetro que la IA aprenda, pero por
simplicidad, hice de la velocidad un argumento CLI que es constante para toda la
sesión de manejo. El automóvil usa modulación de ancho de pulso (PWM) para
cambiar la velocidad, y la CLI del servidor acepta un parámetro de velocidad llamado
"speed_percent" que determina la configuración de PWM en el Pi. Un porcentaje de
velocidad de 100 se traduce en velocidad máxima, mientras que 0 significa que el
automóvil nunca se moverá.
Por lo general, usaré una velocidad más alta (90-100) cuando recopile datos de
entrenamiento y una velocidad mucho menor (40-50) cuando dejo que la IA se haga
cargo. A veces también necesitará ajustar la velocidad para que coincida con el
terreno. Por ejemplo, mi coche es lento en la alfombra, así que cuando la IA maneje en
la alfombra, podría establecer una velocidad de 80 o incluso 100. El siguiente comando
iniciará el servidor que acepta comandos de conducción remota.
http://ryanzotti.local:81/drive
Haga clic en la página y use las teclas de flecha (izquierda, derecha, arriba, abajo) para
conducir el automóvil. La página en la que acabas de hacer clic tiene algo de jacky
javascript que escribí que dispara una llamada API al servidor web que se ejecuta en el
Pi cada vez que presionas una de las teclas de flecha.
http://ryanzotti.local:81/StoreLogEntries
Luego presiona enter. Esto ejecuta un paso importante de limpieza de datos en todos
los comandos que el servidor web recibió durante la sesión de conducción. Una vez
que la página web diga "Finalizado", vaya a la pestaña Terminal / Masilla que ejecuta el
servidor y presione control + c para finalizar el proceso. Has visto ahora dos archivos.
Entonces, en total, hay cuatro archivos para cada sesión de manejo. Normalmente
creo una nueva carpeta para cada sesión. Tenga en cuenta que dos de los archivos
están en el Pi y dos están en su computadora portátil. Sin embargo, los cuatro archivos
deben estar en el mismo lugar para el procesamiento, por lo que normalmente copio
los archivos Pi en mi computadora portátil. Tendrá que generar muchos datos de
manejo, y copiar los archivos del Pi a su computadora portátil puede ser
tedioso. Creé scp_car_data.shpara hacer esto más fácil.
Una vez que todos los archivos estén en el mismo lugar, es hora de limpiar todos sus
datos y crear archivos que TensorFlow pueda digerir para la capacitación del
modelo. Todo esto sucede en el save_all_runs_as_numpy_files.pyguion. Este script asigna
una etiqueta (izquierda, derecha, recta) a cada imagen y realiza una limpieza de datos
básica. Guarda cada sesión de conducción por separado como un archivo .npz.
# Terminal 1
ssh pi@ryanzotti.local
cd /usr/src/ffmpeg
sudo ffserver -f /etc/ff.conf_original & ffmpeg -v quiet -r 5 -s 320x240 -f video4linux2 -i /dev/video0
http://localhost/webcam.ffm
# Terminal 2
ssh pi@ryanzotti.local
cd /home/pi/Documents/code/Self-Driving-Car
sudo su
python3 drive_api.py --speed_percent 100
# Terminal 3
cd /Users/ryanzotti/Documents/repos/Self-Driving-Car
python save_streaming_video_data.py --host ryanzotti.local
Copias de seguridad
Recomiendo hacer una copia de seguridad de sus datos en algún lugar como el S3 de
AWS. Vea ejemplos de línea de comandos a continuación.
Tenga en cuenta que sin el --deleteindicador, el aws synchcomando no borrará los datos
de S3, sino que lo agregará si no existe. Esto es útil para que no borre accidentalmente
toda su copia de seguridad.
El syncomando es recursivo, por lo que puede copiar archivos dentro de carpetas
anidadas.
# Specify your own locations
LOCAL_FOLDER='/Users/ryanzotti/Documents/repos/Self_Driving_RC_Car/data'
S3_FOLDER='s3://self-driving-car/data'
# To back up to AWS
aws s3 sync ${LOCAL_FOLDER} ${S3_FOLDER}
# You can also delete unwanted files from the AWS backup
aws s3 sync ${LOCAL_FOLDER} ${S3_FOLDER} --delete
El comando anterior puede tomar un tiempo extremadamente largo dependiendo de
la velocidad de su conexión a Internet. En un momento tuve un plan básico de Internet
de AT & T básico con solo una velocidad de carga de 250 kbps (anunciado a 5 Mbps), y
tardé entre 5 y 8 horas en cargar aproximadamente una hora de datos de conducción.
Para ejecutar todos estos comandos AWS localmente, debe informar a AWS que tiene
acceso. AWS hace esto con aws_secret_access_keyy aws_access_key_id. Cuando activa una
instancia de AWS (por ejemplo, una GPU), puede asignar un AWS IAM Rolea la instancia
y la instancia heredará estas credenciales. Sin embargo, AWS no puede asignar un rol
de IAM a su computadora portátil, por lo que deberá actualizar ~/.aws/credentialspara
que se parezca a los contenidos a continuación. Obviamente, estos son valores falsos,
pero los valores reales se parecen tanto a las largas cadenas de galimatías. Puede
obtener los valores reales asociados con su cuenta a través de la consola AWS
IAM. Nunca debe exponer sus valores reales al público: los ladrones podrían tomar el
control de toda su cuenta de AWS y, por ejemplo, ejecutar una factura masiva, entre
otras cosas.
[default]
aws_access_key_id = ASDFSDFSDFSDFSDFKKJSDFEUSXN
aws_secret_access_key = SKJE8ss3jsefa3sjKSDWdease3kjsdvna21
region = us-east-1
Los datos de video ocupan mucho espacio en su máquina local. Reviso periódicamente
la cantidad de almacenamiento que he usado ejecutando el siguiente comando.
DATA_DIR='/Users/ryanzotti/Documents/repos/Self_Driving_RC_Car/data'
du -sh ${DATA_DIR}
Procesamiento de datos
Al comienzo de mi proyecto, confié en dataprep.pyagregar todos los datos de imágenes y
etiquetas de mis sesiones en un único archivo para el entrenamiento modelo. A
medida que mi conjunto de datos creció, mi laptop de 16 GB de memoria comenzó a
tener problemas de memoria al procesar todos los archivos simultáneamente. Mi
límite parecía ser 44,000 imágenes de 240x320x3.
Como no quiero gastar dinero en un clúster GPU Apache Spark, decidí probar mis
datos usando el Dataset.pyscript y la Datasetclase. Datasetasume que ya ha ejecutado
el save_all_runs_as_numpy_files.pyscript. La Datasetclase debe crearse una instancia en cada
secuencia de comandos de capacitación del modelo, ya que ahora también se encarga
de crear lotes.
Entrenamiento modelo
El entrenamiento en la GPU es mucho más rápido que el entrenamiento en la CPU que
ahora solo entreno en la GPU, excepto cuando se depura. Tengo una velocidad de
hasta 14x cuando uso una de las GPU Tesla K80 de AWS (p2.xlarge) en comparación
con la CPU de mi Mac. Las Mac no tienen una GPU incorporada soportada por
Tensorflow, así que confío en AWS para hacer mi entrenamiento de GPU.
He escrito guiones para entrenar diferentes tipos de modelos. Para evitar confusiones,
he estandarizado las entradas de la interfaz de línea de comandos en todos los scripts
al aprovechar la misma Trainerclase Trainer.py. Todos los scripts sincronizan / archivan
datos automáticamente con AWS's S3. Esto significa que el modelo siempre entrenará
en el último lote de datos de entrenamiento. También significa que debe estar
preparado para descargar TODOS los datos de capacitación, que a partir de ahora son
aproximadamente 50 GB. Asegúrese de que su computadora portátil o GPU tenga
suficiente espacio antes de intentarlo.
Cada secuencia de comandos se sincroniza con S3 antes del entrenamiento, por lo que
es posible entrenar varios modelos en paralelo sin que las copias de seguridad se
sobrescriban entre sí. La Trainerclase escribe copias de seguridad en S3 después de cada
época.
Entrenar un nuevo modelo es simple. Vea el ejemplo a continuación. El nohupy &decirle
el modelo para entrenar en el fondo para que pueda cerrar el ordenador (suponiendo
que el código se ejecuta en la nube y no en local).
S3_BUCKET=self-driving-car # Specify your own S3 bucket
SCRIPT=train_conv_net.py
# Optionally, in development mode, avoid syncing to save money on S3 data transfers
S3_SYNC=n
# Or on a GPU
DATA_PATH='/root/data'
EPOCHS=100
MODEL_DIR='/root/data/tf_visual_data/runs/4'
S3_BUCKET=self-driving-car