Visualización de datos con Lidar-Visualizer
Visualización de datos con Lidar-Visualizer
Esta semana he estado investigando más en profundidad las funcionalidades del simulador Carla para poder visualizar nubes de puntos con la herramienta Lidar-Visualizer mientras se pilota un vehículo.
Escenario en Carla y captura de datos con sensor LiDAR
He creado un escenario con un vehículo y le he aplicado un sensor LiDAR para probar la generación de datos. A continuación, se muestran las líneas de código con el que se ha realizado la simulación:
import carla
# Conectar con el servidor del simulador
client = carla.Client('localhost', 2000)
world = client.get_world()
#Generar escenario
client.load_world('Town05')
# Librería de vehículos
vehicle_blueprints = world.get_blueprint_library().filter('*vehicle*')
# Cogemos todos los puntos de aparición predefinidos del escenario
spawn_points = world.get_map().get_spawn_points()
# Seleccionamos un vehículo de la librería
vehicle_bp = vehicle_blueprints.find('vehicle.audi.tt')
# Generamos nuestro vehículo en el primer puntos de aparición del escenario
ego_vehicle = world.spawn_actor((vehicle_bp), (spawn_points[0]))
# Asignar posición al objeto
lidar_transform = carla.Transform(carla.Location(z=2.5))
# Filtramos por tipo de actores: asignamos sensor LiDAR
lidar_bp = world.get_blueprint_library().find('sensor.lidar.ray_cast')
lidar_bp.set_attribute('channels', '128') # Número de rayos
lidar_bp.set_attribute('range', '100') # Alcance en metros
lidar_bp.set_attribute('rotation_frequency', '10') # Hz
lidar_bp.set_attribute('points_per_second', '500000')
# Asignamos sensor a nuestro vehículo
sensor_lidar = world.spawn_actor(lidar_bp, lidar_transform, attach_to=ego_vehicle)
# Iniciar sensor en modo escucha
sensor_lidar.listen(lidar_callback)
# Activar piloto automático del vehículo
ego_vehicle.set_autopilot(True)
Para extraer los datos que genere el sensor, he usado una función lidar_callback para almacenarlos automaticamente como ficheros .ply con la finalidad de poder visualizarlos como datos en modo local con el visualizador LiDAR (a modo de prueba). Esta función recibe como argumento el objeto de datos LiDAR (point_cloud). Para almacenar los ficheros .ply se ha usado el módulo plyfile:
def lidar_callback(point_cloud, frame_count=[0]):
# Convertir datos LIDAR a un array Nx4: x, y, z, intensidad
points = np.frombuffer(point_cloud.raw_data, dtype=np.float32)
points = np.reshape(points, (-1, 4))
#Crear array estructurado para PLY
vertices = np.array(
[tuple(p) for p in points],
dtype=[('x','f4'),('y','f4'),('z','f4'),('intensity','f4')]
)
# Preparar carpeta de salida
output_folder = 'Visualizador'
# Generar el nombre del archivo .PLY
# Se numera automáticamente usando frame_count
file_path = os.path.join(output_folder, f"frame{frame_count[0]:06d}.ply")
# Guardar el archivo en formato PLY de texto
PlyData([PlyElement.describe(vertices, 'vertex')], text=True).write(file_path)
frame_count[0] += 1
print("LiDAR data received: ", point_cloud)
Posteriormente, he visualizado la nube de puntos generada en el simulador.
Control de un vehículo en Carla
El siguiente paso, fue el de conseguir controlar un vehículo mientras generaba datos con el sensor LiDAR (tarea que también ofrece el propio visualizador). Para comprender su funcionamiento, he realizado un script para teleoperar un vehículo y poder visualizar los datos generados por el LiDAR. Para detectar el teclado, manejar la pantalla de las cámaras y manejar la sincronización de los eventos, se ha usado la librería Pygame.
Para ello, se ha implementado:
- vehicle_controller: permite el control de un vehículo (un coche en este caso).
def vehicle_controller(vehicle):
control = carla.VehicleControl()
# Leer teclado
keys = pygame.key.get_pressed()
# valores iniciales
control.throttle = 0.0
control.steer = 0.0
control.brake = 0.0
control.hand_brake = False
# W acelerar
if keys[pygame.K_w]:
control.throttle = 1.0
# S frenar
if keys[pygame.K_s]:
control.brake = 1.0
# A girar a la izquierda
if keys[pygame.K_a]:
control.steer = -0.5 # negativo = izquierda
# D : girar a la derecha
if keys[pygame.K_d]:
control.steer = 0.5 # positivo = derecha
# Aplicar control al vehículo
vehicle.apply_control(control)
- camera_callback: para procesar las imágenes que genere la cámara situada en la parte superior del vehículo, con tal de poder visualizarlo durante su control.
def camera_callback(image, display):
array = np.frombuffer(image.raw_data, dtype=np.uint8)
array = np.reshape(array, (image.height, image.width, 4))
array = array[:, :, :3] # Quitar el canal alfa
array = array[:, :, ::-1] # Convertir de BGRA a RGB
surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
display.blit(surface, (0, 0))
# Actualizar solo esta superficie en vez de toda la pantalla
pygame.display.update(display.get_rect())
Además de las funciones comentadas anteriormente, he omitido el uso de las funciones set_lidar y lidar_callback, pues me han generado errores a resolver próximamente en el procesamiento de los datos del sensor. A continuación, la función main(), con la que he simulado el entorno en Carla:
def main():
pygame.init()
pygame.display.gl_set_attribute(pygame.GL_ACCELERATED_VISUAL, 0)
width, height = 800, 600
screen = pygame.display.set_mode((width, height), pygame.SRCALPHA)
pygame.display.set_caption("Carla Simulator")
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)
client.load_world('Town05')
world = client.get_world()
blueprint_library = world.get_blueprint_library()
traffic_manager = client.get_trafficmanager(8000)
traffic_manager.set_synchronous_mode(True)
traffic_manager.set_global_distance_to_leading_vehicle(2.5)
settings = world.get_settings()
delta = 0.05
settings.fixed_delta_seconds = delta
settings.synchronous_mode = True
world.apply_settings(settings)
# Librería de vehículos
vehicle_blueprints = world.get_blueprint_library().filter('*vehicle*')
# Cogemos todos los puntos de aparición predefinidos del escenario
spawn_points = world.get_map().get_spawn_points()
# Seleccionamos un vehículo de la librería (escogido a mi gusto)
vehicle_bp = vehicle_blueprints.find('vehicle.audi.tt')
ego_vehicle = world.spawn_actor(vehicle_bp, spawn_points[0])
if ego_vehicle is not None:
print('Vehículo spawneado correctamente')
lidar = set_lidar(world,ego_vehicle)
camera_bp = blueprint_library.find('sensor.camera.rgb')
camera_bp.set_attribute('image_size_x', '800')
camera_bp.set_attribute('image_size_y', '600')
camera_bp.set_attribute('fov', '90')
camera_transform = carla.Transform(carla.Location(x=-4.0, z=2.5))
camera = world.spawn_actor(camera_bp, camera_transform, attach_to=ego_vehicle)
actor_list = []
actor_list.append(ego_vehicle)
actor_list.append(camera)
camera.listen(lambda image: camera_callback(image, screen))
clock = pygame.time.Clock()
while True:
world.tick() # avanzar simulación
vehicle_controller(ego_vehicle) # control del vehículo
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.flip() # refrescar la ventana
clock.tick(20) # sincronizar a ~20 FPS
if ego_vehicle is None:
break
Resumen
Esta semana se ha logrado capturar y procesar datos generados por un sensor LiDAR en Carla, aptas para su visualización, y la simulación de un escenario en dicho simulador en que se pueda controlar un automóvil. Además de la mejor comprensión del simulador.
Solucionar: procesamiento y almacenamiento de datos mientras se controla el vehículo en el simulador.