RobotCleanPupusas / robot_detector.py
Trujasx's picture
backend done
5ed0597
# backend/robot_detector.py
import serial.tools.list_ports
import gradio as gr
import json
import os
# Define the path to save/load configurations
CONFIG_FILE = "config/default_config.json"
def list_serial_ports():
"""
Lista todos los puertos seriales disponibles en el sistema.
"""
ports = serial.tools.list_ports.comports()
port_list = []
if not ports:
return ["No se encontraron puertos seriales disponibles."]
for port in ports:
port_info = f"{port.device} - {port.description}"
if port.hwid and "VID:PID" in port.hwid:
port_info += f" ({port.hwid})"
port_list.append(port_info)
return port_list
def save_config(follower_port: str, follower_id: str, leader_port: str, leader_id: str):
"""
Guarda la configuraci贸n del robot y teleoperador en un archivo JSON.
"""
config = {
"robot_follower": {
"port": follower_port.split(' ')[0] if follower_port else "", # Extract only device path
"id": follower_id
},
"teleop_leader": {
"port": leader_port.split(' ')[0] if leader_port else "", # Extract only device path
"id": leader_id
}
}
try:
with open(CONFIG_FILE, 'w') as f:
json.dump(config, f, indent=4)
return f"Configuraci贸n guardada en {CONFIG_FILE} correctamente."
except Exception as e:
return f"Error al guardar la configuraci贸n: {e}"
def load_config():
"""
Carga la configuraci贸n del robot y teleoperador desde un archivo JSON.
"""
if os.path.exists(CONFIG_FILE):
try:
with open(CONFIG_FILE, 'r') as f:
config = json.load(f)
return (
config.get("robot_follower", {}).get("port", ""),
config.get("robot_follower", {}).get("id", ""),
config.get("teleop_leader", {}).get("port", ""),
config.get("teleop_leader", {}).get("id", "")
)
except Exception as e:
gr.Warning(f"Error al cargar la configuraci贸n existente: {e}. Se usar谩n valores por defecto.")
return "", "", "", ""
return "", "", "", ""
# --- Gradio Interface ---
# Load initial config values for Gradio components
initial_follower_port, initial_follower_id, initial_leader_port, initial_leader_id = load_config()
with gr.Blocks(title="Detector y Configuraci贸n de Robots LeRobot") as demo:
gr.Markdown("# <center>Detector y Configuraci贸n de Robots LeRobot</center>")
gr.Markdown(
"Esta herramienta te ayuda a identificar los puertos seriales de tus robots "
"SO101 (follower y leader) y asignarles un ID consistente."
)
with gr.Tab("1. Detectar Puertos Seriales"):
gr.Markdown("## Puertos Seriales Detectados")
gr.Markdown(
"Conecta tus robots SO101 (follower y leader) a tu computadora y haz clic en 'Refrescar Puertos'. "
"Observa la lista y compara con los nombres de tus dispositivos si es posible para identificarlos."
)
refresh_btn = gr.Button("馃攧 Refrescar Puertos")
port_list_output = gr.Textbox(
label="Puertos Seriales Disponibles",
interactive=False,
lines=10,
value="\n".join(list_serial_ports()), # Initial list on startup
show_copy_button=True
)
refresh_btn.click(
fn=lambda: "\n".join(list_serial_ports()),
inputs=None,
outputs=port_list_output
)
with gr.Tab("2. Asignar Puertos e IDs"):
gr.Markdown("## Asignaci贸n de Robots y Teleoperadores")
gr.Markdown(
"Selecciona el puerto correcto para cada dispositivo y asigna un ID 煤nico. "
"**隆Es crucial usar el mismo ID en todos los scripts (grabaci贸n, entrenamiento, evaluaci贸n)!**"
)
gr.Markdown("### Robot Follower (Brazo del Robot SO101)")
follower_port_dropdown = gr.Dropdown(
label="Puerto Serial del Robot Follower",
choices=[], # Will be populated dynamically
value=initial_follower_port,
info="Selecciona el puerto donde est谩 conectado el brazo del robot (SO101)."
)
follower_id_input = gr.Textbox(
label="ID del Robot Follower",
value=initial_follower_id if initial_follower_id else "my_robot_follower_arm",
placeholder="ej. my_robot_follower_arm",
info="Un identificador 煤nico para este robot. Usado para archivos de calibraci贸n."
)
gr.Markdown("### Teleoperador Leader (Brazo de Control SO101)")
leader_port_dropdown = gr.Dropdown(
label="Puerto Serial del Teleoperador Leader",
choices=[], # Will be populated dynamically
value=initial_leader_port,
info="Selecciona el puerto donde est谩 conectado el dispositivo de control (SO101)."
)
leader_id_input = gr.Textbox(
label="ID del Teleoperador Leader",
value=initial_leader_id if initial_leader_id else "my_teleop_leader_arm",
placeholder="ej. my_teleop_leader_arm",
info="Un identificador 煤nico para el dispositivo de teleoperaci贸n."
)
save_btn = gr.Button("馃捑 Guardar Configuraci贸n", variant="primary")
save_status_output = gr.Textbox(
label="Estado de Guardado",
interactive=False,
visible=False
)
save_btn.click(
fn=save_config,
inputs=[follower_port_dropdown, follower_id_input, leader_port_dropdown, leader_id_input],
outputs=save_status_output
)
# Function to update dropdown choices based on current ports
def update_port_choices():
ports = list_serial_ports()
# Extract just the device path for dropdown value (e.g., /dev/tty.usbmodemXXX)
device_paths = [p.split(' ')[0] for p in ports if "No se encontraron" not in p]
return gr.update(choices=device_paths), gr.update(choices=device_paths)
# Update dropdowns on initial load and when refresh button is clicked
demo.load(
fn=update_port_choices,
inputs=None,
outputs=[follower_port_dropdown, leader_port_dropdown]
)
refresh_btn.click( # Re-bind refresh button to update dropdowns too
fn=update_port_choices,
inputs=None,
outputs=[follower_port_dropdown, leader_port_dropdown]
)
gr.Markdown("---")
gr.Markdown(f"**La configuraci贸n guardada se almacenar谩 en:** `{os.path.abspath(CONFIG_FILE)}`")
gr.Markdown(
"**Instrucciones para otros scripts:**\n"
"1. Abre `robot_config.json`.\n"
"2. Copia los valores de `port` y `id` a tus scripts de `record_controller.py` y `train_robot.py` (para evaluaci贸n)."
)
gr.Markdown("Hecho con 鉂わ笍 para RobotCleanPupusas503")
if __name__ == "__main__":
try:
import serial # Test if pyserial is installed
except ImportError:
print("Error: La librer铆a 'pyserial' no est谩 instalada.")
print("Por favor, instala 'pyserial' ejecutando: pip install pyserial")
exit(1)
demo.launch(share=False)