Tutorial · Principiante · 17 min de lectura
Maquinas de estados finitos para el comportamiento de robots
Máquina de estados finitos para robots: transiciones explícitas, esperas, recuperación, actualizaciones no bloqueantes y reglas de seguridad verificables.
Los programas de robot empiezan a menudo como un bucle lleno de sentencias if: sigue la linea salvo que haya un obstaculo cerca, gira hasta que el camino se despeje, parate cuando la bateria este baja y recuperate de algun modo cuando un sensor se agote. A medida que crecen los comportamientos, la misma condicion puede disparar ordenes contradictorias.
Una maquina de estados finitos (FSM) hace explicito el comportamiento activo. En cada instante el robot esta en un estado; los eventos y las guardas determinan cuando transiciona a otro. El patron es lo bastante pequeno para un Arduino y lo bastante estructurado para poder probarlo.
Separa estado, evento y accion
Un estado describe lo que el robot esta haciendo a lo largo del tiempo: FOLLOW_LINE, AVOID, SEARCH o FAULT. Un evento es algo observado: un obstaculo entra en la zona de parada, se pierde la linea, expira un tiempo de espera o el operador pulsa parada. Una accion es la salida: fijar velocidades de rueda, limpiar un integrador o levantar una alerta.
Evita crear estados para hechos instantaneos. OBSTACLE_DETECTED suele ser un evento o una guarda; AVOIDING_OBSTACLE es un estado porque persiste mientras el robot ejecuta un comportamiento.
Empieza por una tabla de transiciones antes de escribir codigo:
| Estado actual | Guarda o evento | Estado siguiente | Accion de entrada |
|---|---|---|---|
| Idle | Arranque solicitado y sensores validos | Follow | Reiniciar controlador |
| Follow | Obstaculo dentro del umbral de parada | Avoid | Detener el avance |
| Follow | Linea perdida durante 200 ms | Search | Recordar el ultimo lado |
| Avoid | Camino despejado durante 500 ms | Follow | Reiniciar controlador |
| Cualquier estado activo | Tiempo de espera de sensor | Fault | Detener motores |
| Fault | Reinicio del operador y salud valida | Idle | Limpiar el fallo |
La tabla saca a la luz los casos que faltan y hace visible la prioridad de seguridad.
Manten el bucle de actualizacion sin bloqueos
Un estado debe hacer una actualizacion pequena y volver. Un delay() de dos segundos dentro de AVOID impide que el programa vea una peticion de parada o un fallo de sensor durante esos dos segundos.
enum class State { Idle, Follow, Avoid, Search, Fault };
State state = State::Idle;
unsigned long enteredAt = 0;
void transitionTo(State next) {
state = next;
enteredAt = millis();
}
void loop() {
Sensors s = readSensors();
if (!s.healthy && state != State::Fault) transitionTo(State::Fault);
switch (state) {
case State::Idle: updateIdle(s); break;
case State::Follow: updateFollow(s); break;
case State::Avoid: updateAvoid(s); break;
case State::Search: updateSearch(s); break;
case State::Fault: updateFault(s); break;
}
}
Cada actualizacion lee la instantanea de sensores ya capturada y escribe una orden coherente de actuadores. Esto evita que distintos estados lean valores cambiantes en momentos distintos dentro de un mismo ciclo.
Situa las transiciones en fronteras claras
Elige una unica regla de propiedad. Un diseno embebido sencillo deja que cada estado pida sus transiciones salientes, mientras que una comprobacion de seguridad de nivel superior puede anular cualquier estado activo.
void updateFollow(const Sensors& s) {
if (s.obstacleMm < stopThresholdMm) {
setWheels(0, 0);
transitionTo(State::Avoid);
return;
}
if (s.lineMissingForMs > 200) {
transitionTo(State::Search);
return;
}
followLine(s.lineError);
}
Vuelve inmediatamente despues de una transicion para que el estado antiguo no pueda tambien ordenar los actuadores. Al entrar en un estado de control, reinicia el historial que no deba filtrarse entre comportamientos, como la integral o la muestra derivativa de un PID.
Usa acciones de salida con moderacion. La mayor parte de la limpieza puede ocurrir en la funcion centralizada transitionTo() o en la ruta de entrada del estado siguiente. Las funciones separadas onEntry, onUpdate y onExit solo resultan utiles cuando varios estados las necesitan de verdad.
Usa tiempos de espera e histeresis como guardas
Los eventos fisicos tienen ruido. Si AVOID sale en el instante en que la distancia sube por encima del mismo umbral que lo activo, el ruido de medicion puede provocar un parloteo rapido entre estados. Usa dos umbrales o un tiempo de persistencia: entra por debajo de 250 mm, pero sal solo despues de que la distancia se mantenga por encima de 350 mm durante 500 ms.
Todo estado que espera progreso necesita un tiempo de espera. Si el robot entra en SEARCH y nunca encuentra la linea, no deberia girar para siempre. Transiciona a FAULT o a una recuperacion acotada tras un intervalo probado.
Basa los temporizadores en el tiempo desde la entrada o desde el ultimo progreso. Usa una resta como now - enteredAt >= timeout, que sigue siendo correcta ante el desbordamiento de un temporizador sin signo cuando los tipos son coherentes.
Da prioridad a las transiciones de seguridad
Define que puede interrumpirlo todo: parada de emergencia, datos criticos de sensor invalidos, fallo del driver de motores o tiempo de espera de un watchdog. Evalua estas condiciones antes de las transiciones propias del comportamiento y haz explicita la salida segura.
Un estado FAULT debe enclavarse cuando una recuperacion automatica podria reiniciar un movimiento peligroso. Exigir un reinicio del operador despues de que la causa desaparezca suele ser mas seguro que saltar directamente de vuelta a FOLLOW.
No dejes que dos maquinas de estados independientes escriban las mismas ordenes de motor sin una regla de arbitraje. Si la navegacion y la gestion de bateria afectan ambas al movimiento, un solo propietario debe seleccionar la orden final y aplicar los limites de seguridad.
Prueba las transiciones sin mover motores
Lleva las decisiones a funciones que aceptan una instantanea de sensores y un tiempo, y devuelven el siguiente estado o una orden. Alimenta una secuencia de instantaneas sinteticas:
- Linea valida y camino despejado permanece en
FOLLOW. - Una unica muestra cercana con ruido no dispara si se exige persistencia.
- Un obstaculo cercano sostenido entra en
AVOIDy ordena parada en primer lugar. - Un camino despejado mantenido durante el intervalo de salida vuelve a
FOLLOW. - Un tiempo de espera de sensor llega a
FAULTdesde cualquier estado activo.
Registra los cambios de estado como antiguo → nuevo, el evento que los dispara y la marca de tiempo. Los registros continuos de cada ciclo ocultan las transiciones en el ruido; los registros de transiciones explican por que cambio el comportamiento.
Sabe cuando una FSM deja de ser el modelo mas sencillo
Una FSM funciona bien cuando el robot tiene un numero modesto de modos mutuamente excluyentes. Se vuelve dificil cuando los estados se multiplican para representar combinaciones como “navegar mientras se vigila la bateria mientras se reintenta la localizacion”. El numero de transiciones puede crecer mas rapido que los propios comportamientos.
Los arboles de comportamiento componen acciones reutilizables con estructura de secuencia, alternativa y recuperacion, y por eso sistemas de navegacion como Nav2 los usan para tareas complejas. No introduzcas un framework de arboles de comportamiento para cuatro estados. Cambia cuando la tabla de transiciones resulte de verdad dificil de revisar o los comportamientos necesiten reutilizacion jerarquica.
Diagnostica fallos de diseno habituales
- El robot ignora la parada mientras gira: un estado contiene un bucle bloqueante o un delay.
- Los motores reciben dos ordenes por ciclo: el codigo de transicion sigue ejecutandose despues de cambiar de estado.
- La maquina parlotea: las guardas ruidosas carecen de histeresis o persistencia.
- La recuperacion nunca termina: el estado no tiene condicion de progreso ni tiempo de espera.
- Un fallo reinicia el movimiento al instante: los fallos de seguridad no estan enclavados o las condiciones de reinicio son demasiado debiles.
- Probarlo exige el robot entero: las decisiones y el acceso al hardware estan mezclados en lugar de usar instantaneas de sensores y ordenes de salida.
El simulador de evitacion de obstaculos ofrece una secuencia de comportamiento util para modelar: avanzar, esquivar una amenaza, llegar o detenerse cuando no queda movimiento seguro. El simulador de resolucion de laberintos muestra otra separacion entre sensado, actualizacion del mapa, planificacion y movimiento de una celda. El robot mini sumo es la prueba mas dura de la regla de seguridad enclavada anterior: su reflejo de borde tiene que anticiparse a cualquier otro estado, desde cualquier estado, o el robot se sale del ring por si solo.
Explora el grafo
Forma parte de estos montajes
Proyectos y rutas de aprendizaje que incluyen este tutorial.
- ProyectoConstruye un robot controlado por móvil con Bluetooth o Wi-Fi
- ProyectoConstruye un robot mini sumo: tracción, cuña y borde
- ProyectoConstruye un robot pick and place con agarre verificado
- ProyectoConstruye un robot ROS 2 que localiza marcadores visuales
- Ruta de aprendizajeAgarre y efectores finales: cómo sujetar piezas
- Ruta de aprendizajeNavegación reactiva: evasión de obstáculos en robótica
Lecturas adicionales