Nota

Hola, bienvenido a la comunidad de entusiastas de SunFounder Raspberry Pi & Arduino & ESP32 en Facebook. ¡Explora más a fondo Raspberry Pi, Arduino y ESP32 con otros entusiastas!

¿Por qué unirse?

  • Soporte experto: Resuelve problemas postventa y desafíos técnicos con la ayuda de nuestra comunidad y equipo.

  • Aprende y comparte: Intercambia consejos y tutoriales para mejorar tus habilidades.

  • Avances exclusivos: Obtén acceso anticipado a anuncios de nuevos productos y vistas previas.

  • Descuentos especiales: Disfruta de descuentos exclusivos en nuestros productos más recientes.

  • Promociones festivas y sorteos: Participa en sorteos y promociones de temporada.

👉 ¿Listo para explorar y crear con nosotros? Haz clic en [aquí] y únete hoy mismo.

14. Galería de acciones

Este ejemplo proporciona un menú interactivo que le permite activar una variedad de acciones preprogramadas para PiCrawler, incluyendo saludar, estrechar la mano, luchar, asentir con la cabeza, hacer flexiones y más.

Ejecutar el código

cd ~/picrawler/examples
sudo python3 14_action_gallery.py

Después de ejecutar el programa, se imprime una lista numerada de las acciones disponibles en el terminal. Escriba el número de la acción que desee y presione Enter para ejecutarla. Presione Enter de nuevo para repetir la última acción.

Si se presiona Ctrl+C, el programa sale de forma segura y el robot vuelve a la posición sentada.

Código

Nota

Puede Modificar/Restablecer/Copiar/Ejecutar/Detener el código siguiente. Pero antes, debe ir a la ruta del código fuente como picrawler\examples. Después de modificar el código, puede ejecutarlo directamente para ver el efecto.

from time import sleep

BODY_LENGTH = 77
BODY_WIDTH = 77
BODY_DIAGONAL = 108.9
DELTA = 45


def sit(spider):
    spider.do_action('sit', speed=40)


def stand(spider):
    spider.do_action('stand', speed=40)


def look_up(spider):
    coords = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -76], [45, 0, -76], [45, 0, -38], [45, 45, -30]],
    ]

    for coord in coords:
        spider.do_step(coord, 60)


def look_down(spider):
    coords = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -28], [45, 0, -40], [45, 0, -68], [45, 45, -76]],
    ]
    for coord in coords:
        spider.do_step(coord, 60)


def dance(spider):
    spider.do_action('dance', speed=60)


def wave_hand(spider):
    coords = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        # wave hand
        [[45, 45, -70], [60, 0, 120], [45, 0, -60], [45, 45, -30]],
        [[45, 45, -70], [-20, 60, 120], [45, 0, -60], [45, 45, -30]],
        [[45, 45, -70], [60, 0, 120], [45, 0, -60], [45, 45, -30]],
        [[45, 45, -70], [-20, 60, 120], [45, 0, -60], [45, 45, -30]],
        # return to stand
        [[45, 45, -50], [45, 0, -30], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -40], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    for coord in coords:
        spider.do_step(coord, 58)


def shake_hand(spider):
    coords = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        # shake hand
        [[45, 45, -65], [5, 280, 80], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, 100], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, -10], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, 100], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, -10], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, 100], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, -10], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 100, 10], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 100, 10], [45, 0, -60], [45, 45, -40]],
        # return to stand
        [[45, 45, -50], [45, 0, -30], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -40], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    for coord in coords:
        spider.do_step(coord, 52)


def fighting(spider):
    ready = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        # fighting ready
        [[45, 45, -40], [45, 0, -40], [50, 20, -20], [45, 45, -50]],
        [[45, 45, -40], [45, 0, -40], [40, 20, -45], [45, 45, -50]],
        [[45, 45, -40], [45, 0, -40], [60, 40, -60], [45, 45, -40]],
        #
        [[45, 45, -40], [45, 30, -30], [60, 40, -60], [45, 45, -40]],
        [[45, 45, -30], [45, 30, -30], [60, 40, -60], [60, 40, -60]],
    ]

    twist_butt = [
        # twist butt
        [[55, 7, -30], [19, 48, -30], [77, 12, -60], [36, 63, -60]],
        [[19, 48, -30], [55, 7, -30], [36, 63, -60], [77, 12, -60]],
        #
        [[55, 7, -30], [19, 48, -30], [77, 12, -60], [36, 63, -60]],
        [[19, 48, -30], [55, 7, -30], [36, 63, -60], [77, 12, -60]],
        #
        [[40, 30, -30], [40, 30, -30], [60, 40, -60], [60, 40, -60]],
        # shrink
        [[40, 50, -30], [40, 50, -30], [60, 20, -60], [60, 20, -60]],
    ]

    pounce_bite = [
        [[40, 40, -60], [20, 60, 110], [60, 60, -60], [60, 60, -60]],
        [[40, 40, -40], [20, 30, -40], [60, 60, -60], [60, 60, -60]],
        [[20, 60, 110], [20, 30, -60], [60, 60, -60], [60, 60, -60]],
        [[20, 30, -40], [20, 30, -40], [60, 60, -60], [60, 60, -60]],
    ]

    return_stand = [
        [[45, 45, -50], [45, 0, -30], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -40], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    for coord in ready:
        spider.do_step(coord, 50)
    for coord in twist_butt:
        spider.do_step(coord, 52)
    sleep(0.2)
    for coord in pounce_bite:
        spider.do_step(coord, 40)
        sleep(0.1)
    sleep(1)
    for coord in return_stand:
        spider.do_step(coord, 52)


def excited(spider):
    coords = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        #
        [[45, 45, -30], [45, 0, -30], [45, 0, -30], [45, 45, -30]],
        [[45, 45, -80], [45, 0, -80], [45, 0, -80], [45, 45, -80]],
        [[45, 45, -30], [45, 0, -30], [45, 0, -30], [45, 45, -30]],
        [[45, 45, -80], [45, 0, -80], [45, 0, -80], [45, 45, -80]],
        [[45, 45, -30], [45, 0, -30], [45, 0, -30], [45, 45, -30]],
        [[45, 45, -80], [45, 0, -80], [45, 0, -80], [45, 45, -80]],
        #
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]
    for coord in coords:
        spider.do_step(coord, 40)
        sleep(0.08)


def play_dead(spider):
    sit = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        #
        [[45, 45, -10], [45, 0, -10], [45, 0, -10], [45, 45, -10]],
    ]

    play_dead = [
        [[45, 45, 100], [45, 45, 100], [45, 45, 100], [45, 45, 100]],
        #
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        #
        [[45, 45, 100], [45, 45, 100], [45, 45, 100], [45, 45, 100]],
    ]

    return_stand = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    for coord in sit:
        spider.do_step(coord, 60)
    for coord in play_dead:
        spider.do_step(coord, 55)
    for coord in return_stand:
        spider.do_step(coord, 60)


def nod(spider):
    stand = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    nod = [
        [[45, 45, -80], [45, 0, -50], [45, 0, -20], [45, 45, -30]],
        [[45, 45, -20], [45, 0, -36], [45, 20, -52], [40, 20, -80]],
        [[45, 45, -80], [45, 0, -50], [45, 0, -20], [45, 45, -30]],
        [[45, 45, -20], [45, 0, -36], [45, 20, -52], [40, 20, -80]],
        [[45, 45, -80], [45, 0, -50], [45, 0, -20], [45, 45, -30]],
    ]

    return_stand = [
        [[45, 45, -80], [45, 0, -50], [45, 0, -40], [45, 45, -40]],
        [[45, 45, -60], [45, 0, -50], [45, 0, -40], [45, 45, -40]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    for coord in stand:
        spider.do_step(coord, 60)
    for coord in nod:
        spider.do_step(coord, 45)
    sleep(.2)
    for coord in return_stand:
        spider.do_step(coord, 50)
    sleep(1)


def shake_head(spider):
    ready = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 20, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 20, -30], [45, 20, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 45, -50], [45, 20, -50], [45, 45, -50]],
    ]

    twist_butt = [
        # twist butt
        [[55, 7, -50], [19, 48, -50], [77, 12, -50], [36, 63, -50]],
        [[19, 48, -50], [55, 7, -50], [36, 63, -50], [77, 12, -50]],
        #
        [[51, 15, -50], [27, 43, -50], [72, 22, -50], [45, 56, -50]],
        [[27, 43, -50], [51, 15, -50], [45, 56, -50], [72, 22, -50]],
        #
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
    ]

    return_stand = [
        [[45, 45, -50], [45, 20, -30], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    for coord in ready:
        spider.do_step(coord, 50)
    for coord in twist_butt:
        spider.do_step(coord, 58)
    sleep(.5)
    for coord in return_stand:
        spider.do_step(coord, 52)


def look_left(spider):
    stand = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    look_left = [
        [[45, 0, -50], [45, 45, -50], [45, 45, -50], [45, 0, -50]],
        [[0, 45, -50], [45, 45, -50], [45, 45, -50], [45, 0, -50]],
        [[0, 45, -50], [45, 45, -35], [45, 45, -50], [45, 0, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    for coord in stand:
        spider.do_step(coord, 50)
    for coord in look_left:
        spider.do_step(coord, 50)


def look_right(spider):
    stand = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    look_right = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [0, 45, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -35], [0, 45, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 0, -50], [45, 45, -50], [45, 45, -50], [45, 0, -50]],
    ]

    for coord in stand:
        spider.do_step(coord, 50)
    for coord in look_right:
        spider.do_step(coord, 50)


def warm_up(spider):
    stand = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
    ]

    left_right = [
        [[45, 37, -85], [45, 37, -14], [45, 37, -14], [45, 37, -85]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
        [[45, 37, -85], [45, 37, -14], [45, 37, -14], [45, 37, -85]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
        #
        [[45, 37, -14], [45, 37, -85], [45, 37, -85], [45, 37, -14]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
        [[45, 37, -14], [45, 37, -85], [45, 37, -85], [45, 37, -14]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
    ]

    clockwise = []
    clockwise.append(spider.move_list.move_body_absolute(0, 25, 10))
    clockwise.append(spider.move_list.move_body_absolute(12.5, 21.65, 10))
    clockwise.append(spider.move_list.move_body_absolute(21.65, 12.5, 10))
    clockwise.append(spider.move_list.move_body_absolute(25, 0, 10))
    clockwise.append(spider.move_list.move_body_absolute(21.65, -12.5, 10))
    clockwise.append(spider.move_list.move_body_absolute(12.5, -21.65, 10))
    clockwise.append(spider.move_list.move_body_absolute(0, -25, 10))
    clockwise.append(spider.move_list.move_body_absolute(-12.5, -21.65, 10))
    clockwise.append(spider.move_list.move_body_absolute(-21.65, -12.5, 10))
    clockwise.append(spider.move_list.move_body_absolute(-25, 0, 10))
    clockwise.append(spider.move_list.move_body_absolute(-21.65, 12.5, 10))
    clockwise.append(spider.move_list.move_body_absolute(-12.5, 21.65, 10))
    clockwise.append(spider.move_list.move_body_absolute(0, 25, 10))

    anticlockwise = []
    anticlockwise.append(spider.move_list.move_body_absolute(0, 25, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-12.5, 21.65, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-21.65, 12.5, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-25, 0, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-21.65, -12.5, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-12.5, -21.65, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(0, -25, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(12.5, -21.65, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(21.65, -12.5, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(25, 0, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(21.65, 12.5, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(12.5, 21.65, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(0, 25, 10))

    return_stand = [
        [[45, 45, -50], [45, 45, -40], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]

    for coord in stand:
        spider.do_step(coord, 50)
    sleep(0.5)
    for coord in left_right:
        spider.do_step(coord, 48)
    sleep(.3)
    for coord in clockwise:
        spider.do_step(coord, 58)
    sleep(.3)
    for coord in anticlockwise:
        spider.do_step(coord, 58)
    sleep(.3)
    for coord in return_stand:
        spider.do_step(coord, 50)


def push_up(spider):
    ready = [
        # stand
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        #
        [[60, 10, -60], [60, 0, -60], [20, 60, 10], [10, 65, -40]],
        [[70, 0, -76], [70, 0, -76], [0, 130, -40], [0, 130, -40]],
    ]

    push_up = [
        [[70, 0, -40], [70, 0, -40], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -76], [70, 0, -76], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -40], [70, 0, -40], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -76], [70, 0, -76], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -40], [70, 0, -40], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -76], [70, 0, -76], [0, 130, -40], [0, 130, -40]],
    ]

    for coord in ready:
        spider.do_step(coord,70)
    for coord in push_up:
        spider.do_step(coord, 35)
        sleep(0.1)


actions_dict = {
    "sit": sit,
    "stand": stand,
    "wave_hand": wave_hand,
    "shake_hand": shake_hand,
    "fighting": fighting,
    "excited": excited,
    "play_dead": play_dead,
    "nod": nod,
    "shake_head": shake_head,
    "look_left": look_left,
    "look_right": look_right,
    "look_up": look_up,
    "look_down": look_down,
    "warm_up": warm_up,
    "push_up": push_up,
}


sounds_dict = {

}

if __name__ == "__main__":
    from picrawler import Picrawler

    my_spider = Picrawler()

    actions = list(actions_dict.keys())
    for i, key in enumerate(actions):
        print(f'{i} {key}')

    last_key = None

    try:
        while True:
            key = input()

            if key == '':
                print(actions[last_key])
                actions_dict[actions[last_key]](my_spider)
            else:
                key = int(key)
                if key > (len(actions) - 1):
                    print("Invalid key")
                else:
                    last_key = key
                    print(actions[key])
                    actions_dict[actions[key]](my_spider)

    except KeyboardInterrupt:
        pass
    except Exception as e:
        print(f'Error:\n {e}')
    finally:
        my_spider.do_action("sit", speed=40)
        sleep(.1)

¿Cómo funciona?

  1. Cuando el programa comienza, construye un diccionario de las acciones disponibles e imprime un menú numerado.

    actions_dict = {
        "sit": sit,
        "stand": stand,
        "wave_hand": wave_hand,
        "shake_hand": shake_hand,
        ...
    }
    
    for i, key in enumerate(actions):
        print(f'{i} {key}')
    

    Cada clave en actions_dict es un nombre legible por humanos y cada valor es una función. Este patrón facilita buscar y llamar a la función correcta cuando el usuario ingresa un número.

  2. Bucle de menú interactivo

    while True:
        key = input()
    
        if key == '':
            actions_dict[actions[last_key]](my_spider)
        else:
            key = int(key)
            last_key = key
            actions_dict[actions[key]](my_spider)
    

    El bucle principal espera la entrada del usuario:

    • Ingrese un número para seleccionar y ejecutar inmediatamente una acción.

    • Presione Enter (entrada vacía) para repetir la última acción.

    • Presione Ctrl+C para salir.

  3. ¿Qué es un paso de coordenadas?

    Cada postura se define como una lista de cuatro coordenadas de patas en el formato [[x, y, z], [x, y, z], [x, y, z], [x, y, z]], correspondientes a:

    • Pata delantera derecha (índice 0)

    • Pata delantera izquierda (índice 1)

    • Pata trasera izquierda (índice 2)

    • Pata trasera derecha (índice 3)

    Cada coordenada tiene tres valores:

    • X: posición adelante/atrás de la punta de la pata

    • Y: posición izquierda/derecha de la punta de la pata

    • Z: posición arriba/abajo (más negativo = más alto)

    # Una postura de pie para las cuatro patas
    [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]]
    
  4. Reproducir una secuencia de posturas

    La mayoría de las acciones se construyen a partir de una lista de fotogramas de coordenadas. El método do_step() interpola suavemente los servos desde la postura actual a la postura objetivo.

    coords = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -76], [45, 0, -76], [45, 0, -38], [45, 45, -30]],
    ]
    
    for coord in coords:
        spider.do_step(coord, 60)
    

    El segundo argumento de do_step() es la velocidad (más alto = más rápido). Los valores típicos van de 40 (lento) a 80 (rápido).

  5. Acciones integradas vs. personalizadas

    Algunas funciones usan acciones integradas a través de do_action():

    def sit(spider):
        spider.do_action('sit', speed=40)
    

    Otras construyen posturas manualmente con do_step(), dándole control total sobre la postura del robot.

    def wave_hand(spider):
        coords = [
            [[45, 45, -70], [60, 0, 120], [45, 0, -60], [45, 45, -30]],
            [[45, 45, -70], [-20, 60, 120], [45, 0, -60], [45, 45, -30]],
        ]
        for coord in coords:
            spider.do_step(coord, 58)
    

    El movimiento de saludo alterna la pata delantera derecha entre dos posiciones extremas, creando un gesto de saludo.

  6. Agregar pausas entre movimientos

    La función sleep() inserta pausas entre las fases de movimiento. Esto es útil para acciones multifase como fighting() o nod():

    for coord in twist_butt:
        spider.do_step(coord, 52)
    sleep(0.2)
    for coord in pounce_bite:
        spider.do_step(coord, 40)
        sleep(0.1)
    sleep(1)
    for coord in return_stand:
        spider.do_step(coord, 52)
    

    Las pausas permiten que cada fase se complete visualmente antes de que comience la siguiente.

  7. Uso de move_body_absolute() para movimiento circular

    La función warm_up() demuestra move_body_absolute(), que desplaza el centro del cuerpo en relación con los pies:

    clockwise = []
    clockwise.append(spider.move_list.move_body_absolute(0, 25, 10))
    clockwise.append(spider.move_list.move_body_absolute(12.5, 21.65, 10))
    ...
    

    Al recorrer puntos en un círculo (usando valores seno/coseno), el robot realiza un balanceo corporal circular — un ejercicio de calentamiento que afloja todas las articulaciones.

  8. Salida segura

    finally:
        my_spider.do_action("sit", speed=40)
        sleep(.1)
    

    Sin importar cómo termine el programa (Ctrl+C o error), el bloque finally asegura que el robot regrese a una posición sentada segura.