UD04 · Notebook 2 — Vehículos de Braitenberg¶
Este cuaderno muestra algunos de los vehículos descritos por Valentino Braitenberg en su libro titulado Vehicles: Experiments in Synthetic Psychology.
Este cuaderno muestra algunos de los vehículos descritos por Valentino Braitenberg, basados en sensores de luz y motores de ruedas.Estos vehículos son muy simples, pero muestran comportamientos muy interesantes.
Usaremos aitk.robots para simular vehículos y sensores de luz.
%pip install aitk aitk.robots
from aitk.robots import World, Vehicle, LightSensor, SmellSensor
1. Crea un mundo y un robot¶
El mundo tiene una fuente de luz en el centro, y el robot está equipado con dos sensores de luz en su frente izquierdo y derecho.
world = World(width=150, height=150, scale=3.0, boundary_wall=False)
world.add_bulb("yellow", 75, 75, 0, 50)
Random seed set to: 6823652
Preste atención al código anterior donde hemos creado el mundo, lo hemos establecido para que la pared exterior no sea tratada como un límite. Sin embargo, cuando el robot se acerca a la pared, simplemente se moverá hacia el lado opuesto del mundo.
robot = Vehicle(x=50,y=100,a=90)
robot.add_device(LightSensor(position=(6,-6), name="left-light"))
robot.add_device(LightSensor(position=(6,6), name="right-light"))
world.add_robot(robot)
world.watch()
Image(value=b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x08\x06\x0…
2. Conecte los sensores en las ruedas¶
Consideramos dos formas posibles de conectar los sensores a las ruedas que se muestran a continuación. A la izquierda, los sensores están conectados a las ruedas en el mismo lado del robot. A la derecha, los sensores están conectados a las ruedas en el lado opuesto del robot.

2.1 Conexiones positivas¶
Primero, considere si hacemos positivo estas conexiones. En otras palabras, a medida que aumenta la lectura de luz en un sensor, la rueda conectada a este sensor irá más rápido. Y a medida que disminuya la lectura de luz, la rueda conectada a este sensor irá más lentamente. ¿Qué tipo de comportamiento crearán estos dos tipos de conexiones posibles?
2.1.1 Vehicle 2a¶
Cuando el sensor de la izquierda lea más luz, la rueda de la izquierda irá más rápido haciendo que el robot gire a la derecha. Del mismo modo, cuando el sensor de la derecha lea más luz, la rueda a la derecha irá más rápido haciendo que el robot gire a la izquierda. Veremos lo que pasa.
def vehicle2a(robot):
left = robot["left-light"].get_brightness()
right = robot["right-light"].get_brightness()
robot.speak(f"{int(left*10)}{int(right*10)}")
robot.motors(left, right)
Cada vehículo hablará sobre sus lecturas de luz izquierda y derecha como dos números en una burbuja mientras se mueve. Cuanto más altos sean los números, más luz se detectará. Un "00" indica poca luz detectada en ambos lados. Un "51" indica que la lectura de luz es más fuerte a la izquierda que a la derecha. Un "99" indica que los dos sensores están leyendo valores de luz muy altos.
#mostramos el mundo
world.watch()
Image(value=b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x08\x06\x0…
world.reset()
world.run([vehicle2a])
0it [00:00, ?it/s]
Simulation stopped at: 00:01:19.50; speed 0.99 x real time
Nota: Cada vehículo funcionará continuamente hasta que lo detenga manualmente. Puedes intentar reiniciarlo tantas veces como quieras. Braitenberg describió el comportamiento resultante como miedo porque el robot rápidamente se aleja de la fuente de luz e intenta esconderse en las esquinas.
2.1.2 Vehicle 2b¶
Ahora veremos cómo usar conexiones positivas cruzadas. Cuando el sensor de luz de la izquierda lea más luz, la rueda a la derecha irá más rápido haciendo que el robot gire a la izquierda. Cuando el sensor de luz de la derecha lea más luz, la rueda izquierda irá más rápido haciendo que el robot gire a la derecha. Veamos el resultado.
def vehicle2b(robot):
left= robot["left-light"].get_brightness()
right = robot["right-light"].get_brightness()
robot.speak(f"{int(left*10)}{int(right*10)}")
robot.motors(right, left)
#mostramos el mundo
world.watch()
Image(value=b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x08\x06\x0…
world.reset()
world.run([vehicle2b])
0it [00:00, ?it/s]
Simulation stopped at: 00:00:24.10; speed 0.99 x real time
Braitenberg describió el comportamiento resultante como una agresión porque el robot se mueve rápidamente a la fuente de luz. Si la fuente de luz fuera un obstáculo, el vehículo chocaría constantemente con él. Sin embargo, en este mundo con límites de contorno, el vehículo viaja a través de la luz, volviendo a él desde el otro lado.
2.2 Conexiones negativas¶
Ahora, consideremos que pasa si hacemos que estas conexiones sean negativas o inhibidoras. En otras palabras, a medida que aumente la lectura de luz en un sensor, la rueda conectada a este sensor irá más lenta. Y a medida que disminuye la lectura de luz, la rueda conectada a este sensor irá más rápido. ¿Qué tipo de comportamiento crearán estos dos tipos de conexiones negativas posibles?

2.2.1 Vehicle 3a¶
La velocidad del motor izquierda se inhibe leyendo el sensor de luz izquierda y la velocidad del motor derecha se inhibe leyendo el sensor de luz derecho. Veremos lo que pasa.
def vehicle3a(robot):
left= robot["left-light"].get_brightness()
right = robot["right-light"].get_brightness()
robot.speak(f"{int(left*10)}{int(right*10)}")
robot.motors(1-left,1-right)
#mostramos el mundo
world.watch()
Image(value=b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x08\x06\x0…
world.reset()
world.run([vehicle3a])
0it [00:00, ?it/s]
Simulation stopped at: 00:00:13.20; speed 0.99 x real time
Braitenberg describió el comportamiento resultante como amor porque el robot se dirige a la fuente de luz y se detiene, observando la bombilla sin cesar.
2.2.2 Vehicle 3b¶
A continuación, veremos conexiones negativas cruzadas. La velocidad del motor izquierdo se inhibe por la lectura del sensor de luz de la derecha y la velocidad del motor derecho se inhibe leyendo el sensor de luz de la izquierda.
def vehicle3b(robot):
left= robot["left-light"].get_brightness()
right = robot["right-light"].get_brightness()
robot.speak("%d%d" % (left*10, right*10))
robot.motors(1-right,1-left)
#mostramos el mundo
world.watch()
Image(value=b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x08\x06\x0…
world.reset()
world.run([vehicle3b])
0it [00:00, ?it/s]
Simulation stopped at: 00:00:22.00; speed 0.99 x real time
Braitenberg describió este vehículo como un Explorador porque se aleja de la luz y se mueve rápidamente. El robot se mueve más rápido cuando está lejos de la luz, lo que hace que finalmente se mueva a lo largo de los márgenes de este mundo con límites de contorno.
2.3 Resumen de vehículos simples¶
El siguiente es un resumen de los cuatro tipos simples de vehículos que hemos explorado hasta ahora.
| Vehículo | Conexiones Sensor->Motor | Tipo de conexión | Descripción del comportamiento |
|---|---|---|---|
| 1a | Directo | Excitador | Miedo |
| 1b | Cruzado | Excitador | Agressión |
| 2a | Directo | Inhibidor | Amor |
| 2b | Cruzado | Inhibidor | Explorador |
3. Vehículos más complejos¶
Luego tratamos de combinar aspectos de varios de estos vehículos simples en un vehículo más complejo que responde a múltiples sensores. Creamos un mundo nuevo con dos luces de diferentes colores, una rojo y una verde, y dos conjuntos diferentes de sensores de luz que son sensibles a solo uno de estos colores.
world2 = World(width=150, height=150, scale=3.0, ground_color="tan", boundary_wall=False)
world2.add_bulb("green", 75, 120, 0, 50)
world2.add_bulb("red", 30, 20, 0, 30)
Random seed set to: 1051515
robot2 = Vehicle(x=80,y=30,a=10)
robot2.add_device(LightSensor(position=(4,-4), name="left-red", color_sensitivity="red"))
robot2.add_device(LightSensor(position=(4,4), name="right-red", color_sensitivity="red"))
robot2.add_device(LightSensor(position=(6,-6), name="left-green", color_sensitivity="green"))
robot2.add_device(LightSensor(position=(6,6), name="right-green", color_sensitivity="green"))
world2.add_robot(robot2)
#mostramos el mundo
world2.watch()
Image(value=b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x08\x06\x0…
3.1 Vehicle 3c¶
Este vehículo tiene conexiones excitatorias cruzadas desde sus sensores de luz verde, lo que hace que responda agresivamente a la bombilla verde (el verde significa ir). También tiene conexiones inhibitorias directas de sus sensores de luz roja, lo que hace que respondiera con amor a la bombilla roja (el rojo significa lento/parada). Los motores responderán a la combinación de estos dos factores, lo que lleva a comportamientos más complejos.
Este vehículo hablará sobre sus lecturas de luz verde y roja como cuatro números en una burbuja mientras se mueve. Cuanto más altos sean los números, más luz se detectará.Un "00" indica poca luz detectada en ambos lados.Un "51" indica que la lectura de luz es más fuerte a la izquierda que a la derecha.Un "99" indica que los dos sensores están leyendo valores de luz muy altos.
def vehicle3c(robot):
L_gr = robot["left-green"].get_brightness()
R_gr = robot["right-green"].get_brightness()
L_rd = robot["left-red"].get_brightness()
R_rd = robot["right-red"].get_brightness()
L_speed = (R_gr + 1-L_rd)/2.0
R_speed = (L_gr + 1-R_rd)/2.0
s = f"{int(L_gr*10)}{int(R_gr*10)}{int(L_rd*10)}{int(R_rd*10)}"
robot.speak(s)
robot.motors(L_speed,R_speed)
world2.reset()
world2.run([vehicle3c])
0it [00:00, ?it/s]
Este vehículo se mueve más lentamente cuando detecta la luz roja en el frente, pero no se detiene por completo porque también se ve afectado por sus lecturas de luz verde. Este vehículo también se mueve rápidamente a la luz verde. Cuando puede detectar las dos lámparas simultáneamente, se hace más difícil predecir el comportamiento resultante.
4. Conclusiones¶
Reflexionando sobre el vehículo 3C, Braitenberg afirma que ahora tenemos acceso a una amplia gama de comportamientos diferentes:
"Te invito a considerar la enorme riqueza de diferentes propiedades que podemos dar al vehículo 3C eligiendo varios sensores y varias combinaciones de conexiones no cruzadas, excitatorias e inhibitorias".
Esta es la idea central del libro de Braitenberg: con sensores simples y conexiones simples, podemos crear comportamientos increíbles y complejos.