{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "Hvn6fhp_9njV" }, "source": [ "# UD04 · Notebook 3 — Ejemplos de robots en AITK\n", "\n", "En este ejemplo veremos diferentes tipos de sensores y robots en los que podemos usar en `aitk.robots` y cómo podemos interactuar con ellos." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "vqf8Pute9njW", "outputId": "28a2b2b7-4f49-4bd4-fb93-029429dd118f" }, "outputs": [], "source": [ "%pip install aitk ipykernel" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "id": "BwZlKT8d9njW" }, "outputs": [], "source": [ "from aitk.robots import (\n", " World, Scribbler,\n", " RangeSensor, LightSensor, SmellSensor,\n", " Camera\n", ")\n", "from random import random" ] }, { "cell_type": "markdown", "metadata": { "id": "2Jy9R8r59njX" }, "source": [ "### Un mundo con paredes, una bombilla y comida\n", "\n", "\n", "Hay una fuente de comida ubicada cerca del origen del mundo detrás de una pequeña pared azul inclinada. Hay una fuente de luz cerca del centro del mundo escondida en la esquina de las paredes cian y naranja.\n", "\n", "Usamos la comida y la luz para atraer a los robots. Los robots pueden ver luz y comida y pueden moverse hacia ellos. Los robots también pueden ver las paredes y evitarlas. Obviamente, los robots no comen, este elemento, sin embargo, nos permitirá ver cómo los robots pueden interactuar con los objetos en el mundo." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 617, "referenced_widgets": [ "252e20da773a4f77badcf7d57033cb55", "eb682e33fc6c4453a625621ed85ce9bb" ] }, "id": "wsrTPXNN9njX", "outputId": "0c41e5a8-7a9a-4c77-9b1c-0714ae3a3dcc" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Random seed set to: 9396671\n" ] }, { "output_type": "display_data", "data": { "text/plain": [ "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…" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, "model_id": "252e20da773a4f77badcf7d57033cb55" } }, "metadata": {} } ], "source": [ "# Definimos el mundo\n", "# Creamos un mundo de 200x150 con una escala de 5.0\n", "\n", "world = World(width=200, height=150, scale=5.0)\n", "world.add_wall(\"cyan\", 80, 50, 90, 150)\n", "world.add_wall(\"orange\", 90, 50, 110, 60)\n", "world.add_wall(\"blue\", 0, 35, 25, 30, box=False)\n", "world.add_bulb(\"yellow\", 100, 70, 0, 75.0)\n", "world.add_food(15, 10, 50)\n", "\n", "#Mostramos el mundo y pedimos que se actualice automáticamente\n", "world.watch(width=\"700px\")" ] }, { "cell_type": "markdown", "metadata": { "id": "XPwy0jFD9njX" }, "source": [ "### El robot rojo usa sensores IR\n", "\n", "El robot rojo utiliza sensores IR para detectar y evitar obstáculos. Puede determinar a qué lado gira en función de si el obstáculo está más cerca de su parte delantera derecha o izquierda." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "id": "M9UVJ0AH9njX" }, "outputs": [], "source": [ "robot1 = Scribbler(x=150, y=100, a=35, color=\"red\", name=\"red\")\n", "robot1.add_device(RangeSensor(position=(6,-6),width=57.3,max=20,name=\"left-ir\"))\n", "robot1.add_device(RangeSensor(position=(6,6),width=57.3,max=20,name=\"right-ir\"))\n", "\n", "world.add_robot(robot1)" ] }, { "cell_type": "markdown", "metadata": { "id": "Kvvq8AwG9njX" }, "source": [ "### El robot rosa usa sensores de olor y una cámara\n", "\n", "El robot rosa usa sensores de olor para encontrar comida. También tiene una cámara que puede ver las características del mundo. Puede girar hacia los alimentos detectados a su izquierda o derecha." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "id": "-CxSWZy39njY" }, "outputs": [], "source": [ "robot2 = Scribbler(x=40, y=130, a=75, color=\"pink\", name=\"pink\")\n", "robot2.state[\"timer\"] = 0 # Usamos el diccionario state para guardar variables.\n", " # Esta variable nos ayudará a controlar el tiempo\n", "robot2.add_device(Camera())\n", "robot2.add_device(SmellSensor(position=(6,-6),name=\"left-smell\"))\n", "robot2.add_device(SmellSensor(position=(6,6),name=\"right-smell\"))\n", "\n", "world.add_robot(robot2)" ] }, { "cell_type": "markdown", "metadata": { "id": "y1MomaN-9njY" }, "source": [ "### El robot amarillo usa sensores de luz\n", "\n", "El robot amarillo usa sensores de luz para encontrar una fuente de luz. Puede girar hacia la luz detectada a su izquierda o derecha." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "id": "OjT8NSAk9njY" }, "outputs": [], "source": [ "robot3 = Scribbler(x=60, y=30, a=0, color=\"yellow\", name=\"yellow\")\n", "robot3.add_device(LightSensor(position=(6,-6), name=\"left-light\"))\n", "robot3.add_device(LightSensor(position=(6,6), name=\"right-light\"))\n", "\n", "world.add_robot(robot3)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 599, "referenced_widgets": [ "252e20da773a4f77badcf7d57033cb55", "eb682e33fc6c4453a625621ed85ce9bb" ] }, "id": "MYlslYkx9njY", "outputId": "9201a6a7-4a2a-4c8d-838c-f2bfe59da041" }, "outputs": [ { "output_type": "display_data", "data": { "text/plain": [ "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…" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, "model_id": "252e20da773a4f77badcf7d57033cb55" } }, "metadata": {} } ], "source": [ "world.watch(width=\"700px\")" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 293, "referenced_widgets": [ "e7bc97be255c4dbb993465ba5989f385", "7c27fd2248b94dbdbb72303c0a68da8c", "6f46e30afe064a9f98bfd64207052089", "df0280304bc4499aac0cf49fd86227aa", "7a714a1ae76447a1ae5a5dd0909434fc", "87febbab186749188decf19a421316b2", "f68f2e98982d4ffc81394adf9229175f", "4997403c6199484f9b0ac8f1308f4de8", "6ff003ccd2ac4c39bd4042337b175f58", "76f29629483b4af485a6993f2decb323", "a52269a3600e4a7a8bc04b890e184e58" ] }, "id": "7SsiR1jb9njY", "outputId": "5819c6c6-9852-4ba0-97ab-94ad6b389439" }, "outputs": [ { "output_type": "display_data", "data": { "text/plain": [ "HTML(value='')" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, "model_id": "e7bc97be255c4dbb993465ba5989f385" } }, "metadata": {} }, { "output_type": "display_data", "data": { "text/plain": [ "HTML(value='')" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, "model_id": "df0280304bc4499aac0cf49fd86227aa" } }, "metadata": {} }, { "output_type": "display_data", "data": { "text/plain": [ "HTML(value='')" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, "model_id": "f68f2e98982d4ffc81394adf9229175f" } }, "metadata": {} }, { "output_type": "display_data", "data": { "text/plain": [ "Image(value=b\"\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00\\x00@\\x00\\x00\\x00 \\x08\\x06\\x00\\x00\\x00\\xa2\\x9d~\\x84\\x…" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, "model_id": "76f29629483b4af485a6993f2decb323" } }, "metadata": {} } ], "source": [ "#POV del robot rosa\n", "robot2['camera'].watch()" ] }, { "cell_type": "markdown", "metadata": { "id": "ELlk4biT9njY" }, "source": [ "### El controlador del robot rojo\n", "\n", "El robot rojo deambula por todo el mundo evitando los obstáculos que encuentra. Siempre está avanzando, pero elige cantidades de rotación aleatoria cuando sus sensores de rango frontal están limpios." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "id": "bYroVEWq9njZ" }, "outputs": [], "source": [ "def deambula_amb_infrarojos(robot):\n", " max_val = robot[\"left-ir\"].get_max()\n", " if robot[\"left-ir\"].get_distance() < max_val:\n", " robot.move(0.1, -0.3)\n", " elif robot[\"right-ir\"].get_distance() < max_val:\n", " robot.move(0.1, 0.3)\n", " else:\n", " robot.move(1, random()-0.5)" ] }, { "cell_type": "markdown", "metadata": { "id": "soeTVuvr9njZ" }, "source": [ "### El demonio del robot Rosa\n", "\n", "El robot rosa deambula por todo el mundo buscando comida y evitando los obstáculos, retrocede cuando se queda atascado. Usa una variable de estado llamada *timer* para asegurarse de que incluso en presencia de un olor siempre retrocede al menos cinco pasos cuando encuentra un obstáculo. Si se acerca a la comida lo suficiente, intenta comerla, y si tiene éxito, la ejecución termina devolviendo *True*. De vez en cuando elige un nuevo movimiento errático aleatorio. Si no se activan ninguno de sus casos de prueba, repite el movimiento anterior." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "id": "gxjllQXP9njZ" }, "outputs": [], "source": [ "def busca_menjar(robot):\n", " left_smell = robot[\"left-smell\"].get_reading()\n", " right_smell = robot[\"right-smell\"].get_reading()\n", " diff = left_smell - right_smell\n", " if left_smell+right_smell>1.95 and robot.eat():\n", " robot.move(0,0)\n", " robot.speak(\"¡He comido!\")\n", " return True\n", " # Usamos un temporizador para asegurarme de volver\n", " # por un tiempo mínimo de 5 iteraciones\n", " if robot.state[\"timer\"] > 5:\n", " robot.state[\"timer\"] = 0\n", " if robot.stalled:\n", " robot.state[\"timer\"] = 1\n", " robot.reverse()\n", " elif robot.state[\"timer\"] > 0:\n", " robot.state[\"timer\"] += 1\n", " elif diff > 0.03:\n", " robot.move(1, 0.3)\n", " elif diff < -0.03:\n", " robot.move(1, -0.3)\n", " elif world.time%2 == 0:\n", " robot.move(1.0, random()*0.5-0.25)\n", " else:\n", " pass #Continua en la misma dirección" ] }, { "cell_type": "markdown", "metadata": { "id": "LAQLQDZU9njZ" }, "source": [ "### El controlador del robot amarillo busca la luz\n", "\n", "El objetivo del robot amarillo es encontrar y acercarse a una fuente de luz. Cuando no detecta la luz, el robot deambula. Cuando detecta más luz en un lado, gira hacia la luz. Si se detiene el robot, invierte su movimiento. De vez en cuando genera un nuevo movimiento errático aleatorio. Cuando ninguna de las pruebas se activa, el robot continuará haciendo el movimiento anterior. Cuando sus lecturas de luz pasan un umbral, se detiene e informa que ha encontrado la luz, devuelve `True` y termina la ejecución." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "id": "vDkU372e9njZ" }, "outputs": [], "source": [ "def search_light(robot):\n", " left_light = robot[\"left-light\"].get_brightness()\n", " right_light = robot[\"right-light\"].get_brightness()\n", " diff = left_light - right_light\n", " if left_light + right_light > 1.9:\n", " robot.move(0,0)\n", " robot.speak(\"¡Encontré la luz!\")\n", " return True\n", " if robot.stalled:\n", " robot.reverse()\n", " elif diff > 0.01:\n", " robot.move(1,0.5)\n", " elif diff < -0.01:\n", " robot.move(1,-0.5)\n", " elif world.time%2 == 0:\n", " robot.move(1.0, random()*0.5-0.25)\n", " else:\n", " pass #Continua en la misma dirección" ] }, { "cell_type": "code", "source": [ "# mostramos de nuevo el mundo\n", "world.watch(width=\"700px\")" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 599, "referenced_widgets": [ "252e20da773a4f77badcf7d57033cb55", "eb682e33fc6c4453a625621ed85ce9bb" ] }, "id": "yEJm3L5s_DEj", "outputId": "f501b9b3-07b6-4c97-a41c-3d84769ab990" }, "execution_count": 12, "outputs": [ { "output_type": "display_data", "data": { "text/plain": [ "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…" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, "model_id": "252e20da773a4f77badcf7d57033cb55" } }, "metadata": {} } ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 67, "referenced_widgets": [ "714bc3a24a2c4390b76f3afd687b7335", "a74cb6228ad14912aefcf55d30569f9f", "83619f3d13e44baeb09ca8b9f22e1c15", "c2295eaa89b8467abf8a302bde5d8237", "ae631b907ffb47c3912466e391cf0125", "ddfa0239fd1f488b84b8dd2e83e84841", "73e6a16719784bc298159f791e191f79", "bd1774bf3ef5440d8b0991964254f05f", "3e83280f281b4fe4b9f8f4485bd2a09e", "7218eb1b439744109f9376a27e4616a0", "7b47f2f2742248479187c17779a8b500" ] }, "id": "jP_WD6Uq9njZ", "outputId": "6b811331-b540-408a-a05b-01a4d234aac4" }, "outputs": [ { "output_type": "display_data", "data": { "text/plain": [ " 0%| | 0/400 [00:00