Semana 3 - Procesamiento de muestras GOOSE y Visualización 3D, Sensor LiDAR simulado en CARLA, Exploración de ROSbridge
Esta semana me he dedicado a profundizar en el procesamiento de datos brutos LiDAR de GOOSE, mejorar el visualizador 3D para que represente muestras reales, realizar una primera toma de contacto con la simulación del sensor LiDAR en Carla y explorar el funcionamiento de ROSbrige. A continuación detallo más en profundidad los avances
Procesamiento Binario y Visualización 3D
He desarrollado una nueva versión del visualizador 3D, en la que ahora proceso datos binarios extraídos de un archivo que contiene puntos LiDAR en formato XYZI (coordenadas y valor de intensidad de remisión). Utilizando Plotly, he implementado la visualización de estos puntos de manera similar a la versión anterior, manteniendo la capacidad de representar la nube de puntos en un entorno interactivo. El objetivo es mejorarlo para que puede gestionar datos de distintas fuentes y mostrarlos en una linea temporal dinámica
Estructura del Código
El código se organiza en dos clases principales:
LidarDataReader
- Lee datos LiDAR en formato
XYZI
(coordenadas e intensidad) desde un archivo binario del dataset GOOSE utilizando - Para leer los datos, se utiliza
numpy
para cargar el archivo binario con el métodonp.fromfile()
, que organiza los puntos en un array y los reestructura en un formato de 4 columnas:X
,Y
,Z
e intensidad de remisión
- Lee datos LiDAR en formato
LidarVisualizer
- Hereda de
LidarDataReader
y añade la visualización 3D usando Plotly - Convierte las intensidades de los puntos en colores mediante un colormap y muestra los puntos en un gráfico 3D interactivo
- Hereda de
El código procesa los datos binarios y los visualiza con colores según la intensidad de remisión, manteniendo la estructura de la versión anterior con Plotly
class LidarDataReader:
def __init__(self, file_path):
self.file_path = file_path
self.data = self.read_lidar_data_from_bin()
# Función para leer datos LiDAR desde un archivo .bin del dataset GOOSE
def read_lidar_data_from_bin(self):
try:
# Leer los datos del archivo binario
scan = np.fromfile(self.file_path, dtype=np.float32)
# Los datos LiDAR tienen 4 columnas: X, Y, Z, Intensidad
points = scan.reshape((-1, 4))
return points
except FileNotFoundError:
print(f"Error: No se encontró el archivo {self.file_path}")
return np.array([])
class LidarVisualizer(LidarDataReader):
def __init__(self, file_path):
# Inicializar la clase base con el archivo de datos LiDAR
super().__init__(file_path)
# Función que convierte intensidad a color en formato hexadecimal
def intensity_to_color(self, intensity):
# Normalizamos la intensidad
intensity_normalized = (intensity - intensity.min()) / (intensity.max() - intensity.min())
# Usamos una colormap de matplotlib para visualizar las intensidades
colormap = cm.get_cmap('plasma')
rgba_colors = colormap(intensity_normalized)
# Convertimos los valores rgba a hex para poder mostrarlos con Plotly
hex_colors = [f'#{int(r*255):02x}{int(g*255):02x}{int(b*255):02x}' for r, g, b, _ in rgba_colors]
return hex_colors
# Función que genera un gráfico 3D con Plotly
def plot_lidar_data(self):
if self.data.size == 0:
print("No hay datos LiDAR para visualizar.")
return
# Vilualización con Plotly de la versión anterior
. . . .
. . . .
. . . .
Al ejecutar el código nos mostrará en 3D la muestra que se carga en la ruta del objeto LidarDataReader
Sensor LiDAR simulado en Carla
He desarrollado un script que se ejecuta en paralelo al servidor principal de CARLA. Este script genera un vehículo que conduce automáticamente por las rutas preestablecidas del mundo virtual de CARLA. Al vehículo le acoplo un sensor LiDAR, el cual comienza a tomar muestras mientras el vehículo se desplaza
Estas muestras se muestran por terminal, permitiéndome tener una primera toma de contacto con la generación de datos LiDAR simulados en CARLA
Estructura del Código
- Conexión al servidor
- Se conecta al servidor local de CARLA y obtiene el entorno de simulación (world)
- Creación del vehículo
- Se selecciona un vehículo de la biblioteca de actores de CARLA y se genera en un punto de spawn predefinido
- El vehículo se configura en modo de conducción automática utilizando el método
set_autopilot(True)
- Adición del sensor LiDAR
- Se selecciona y configura un sensor LiDAR simulado con atributos como el rango, la frecuencia de rotación y el número de canales
- El sensor se acopla al vehículo y comienza a capturar datos
- Callback para procesar datos LiDAR
- Se define una función de callback (
lidar_callback
) para procesar los datos LiDAR en tiempo real, mostrando la información por terminal
- Se define una función de callback (
- Lógica de Ejecución
- El script se ejecuta en un bucle infinito hasta que se interrumpe manualmente
- Al finalizar, se detienen y destruyen los actores (vehículo y sensor) creados
import carla
# --------------- Conectar al Servidor principal ------------------ #
# Conectarse al servidor principal de CARLA
client = carla.Client('localhost', 2000)
client.set_timeout(10.0) # Tiempo límite para conectarse
# Obtener el MUNDO del simulador obtenido de la conexión con el servidor
world = client.get_world()
# Obtener Blueprint (Lista de actores disponibles en el Mundo conectado)
blueprint_library = world.get_blueprint_library()
# ---------------- Agregar un ACTOR Vehículo -------------------- #
# Filtramos por tipo de actores: Vehiculo y seleccionamos el primero de la lista resultante
vehicle_00 = blueprint_library.filter('vehicle.*')[0]
# Obtener los puntos de Spawn del MAPA y elegir el primero de la lista resultante
spawn_point = world.get_map().get_spawn_points()[0]
# Spawnear el objeto de Tipo: Actor_Vehiculo (Se crea un nuevo objeto al generarlo)
vehicle = world.spawn_actor(vehicle_00, spawn_point)
# Activar el modo de conducción automática por defecto que odrece carla con el metodo set_autopilot(True)
vehicle.set_autopilot(True)
# ---------------- Agregar un ACTOR Sensor LiDAR y configurar sus atributos -------------------- #
# Filtramos por tipo de actores: Sensores, lidar.raycast (Sensor LiDAR simulado en Carla)
lidar_bp = blueprint_library.find('sensor.lidar.ray_cast')
# Configuración del objeto obtenido de tipo actor_sensor_lidar.raycast
# Configurar Rango MAX del sensor
lidar_bp.set_attribute('range', '40')
# Configurar la Frecuencia de rotación en Hz
lidar_bp.set_attribute('rotation_frequency', '10')
# Configurar número de canales
lidar_bp.set_attribute('channels', '32')
# Configurar frecuencia de muestreo (56 kHz)
lidar_bp.set_attribute('points_per_second', '56000')
# Ubicar el objeto en el espacio (teniendo en cuenta que luego se acoplará al vehículo, solo altura)
lidar_position = carla.Transform(carla.Location(x=0, z=2.5))
# Spawnear el sensor y acoplarlo al objeto de Tipo Actor_Vehiculo
# El tercer parámetro vincula la posición del actor LiDAR a otro objeto de tipo Actor_Vehiculo.
lidar = world.spawn_actor(lidar_bp, lidar_position, attach_to=vehicle)
# Función de callback para procesar los datos LiDAR
def lidar_callback(point_cloud):
print("LiDAR data received: ", point_cloud)
# Activación del método listen() del actor_sensor_lidar.raycast
# "Todos los Actores de Tipo Sensor tienen el método listen() para obtener la información"
lidar.listen(lidar_callback)
# -------------------- Lógica de Ejecución ----------------- #
try:
# Mantener el script corriendo
while True:
world.wait_for_tick()
except KeyboardInterrupt:
pass
finally:
# Parar de escuchar
lidar.stop()
# Destruir objeto spawn_sensor
lidar.destroy()
# Destruir objeto spawn_vehiculo
vehicle.destroy()
Al ejecutar el script mientras el servidor principal está corriendo, se muestran las medidas que va tomando el sensor
Exploración de ROSbridge
He empezado a investigar sobre ROSbridge, una herramienta que permite que ROS se comunique con aplicaciones web o clientes externos que no estén escritos en lenguajes como Python o C++. Esto se logra usando WebSockets y JSON
En mi proyecto, será útil en fases más avanzadas. CARLA generará los datos simulados, y con el paquete carla-ros-bridge, estos se convertirán en mensajes ROS. ROSbridge actuará como el puente para extraer y gestionar los datos LiDAR
Gracias a la API en tiempo real de CARLA, los datos se integrarán fácilmente con ROS, permitiendo análisis y visualización avanzados