Nota

Ciao, benvenuto nella Community SunFounder Raspberry Pi & Arduino & ESP32 su Facebook! Esplora a fondo Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.

Perché unirti a noi?

  • Supporto esperto: Risolvi problemi post-vendita e sfide tecniche con l’aiuto della nostra community e del nostro team.

  • Impara e condividi: Scambia suggerimenti e tutorial per migliorare le tue competenze.

  • Anteprime esclusive: Accedi in anteprima agli annunci di nuovi prodotti.

  • Sconti speciali: Approfitta di sconti esclusivi sui nostri prodotti più recenti.

  • Promozioni festive e giveaway: Partecipa a concorsi e promozioni speciali.

👉 Sei pronto a esplorare e creare con noi? Clicca [qui] e unisciti subito!

14. Galleria delle azioni

Questo esempio fornisce un menu interattivo che ti permette di attivare una varietà di azioni preprogrammate per PiCrawler, tra cui salutare, stringere la mano, combattere, annuire, fare flessioni e altro ancora.

Esegui il codice

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

Dopo aver eseguito il programma, viene stampato un elenco numerato delle azioni disponibili nel terminale. Digita il numero dell’azione desiderata, quindi premi Invio per eseguirla. Premi di nuovo Invio per ripetere l’ultima azione.

Se viene premuto Ctrl+C, il programma termina in modo sicuro e il robot torna in posizione seduta.

Codice

Nota

Puoi Modificare/Reimpostare/Copiare/Eseguire/Fermare il codice qui sotto. Ma prima, devi andare nel percorso del codice sorgente come picrawler\examples. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l’effetto.

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)

Come funziona?

  1. All’avvio del programma, viene creato un dizionario delle azioni disponibili e stampato un menu numerato.

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

    Ogni chiave in actions_dict è un nome leggibile e ogni valore è una funzione. Questo schema semplifica la ricerca e la chiamata della funzione corretta quando l’utente inserisce un numero.

  2. Ciclo del menu interattivo

    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)
    

    Il ciclo principale attende l’input dell’utente:

    • Inserisci un numero per selezionare ed eseguire immediatamente un’azione.

    • Premi Invio (input vuoto) per ripetere l’ultima azione.

    • Premi Ctrl+C per uscire.

  3. Cos’è un passo di coordinate?

    Ogni posizione è definita come un elenco di quattro coordinate per le zampe nel formato [[x, y, z], [x, y, z], [x, y, z], [x, y, z]], corrispondenti a:

    • Zampa anteriore destra (indice 0)

    • Zampa anteriore sinistra (indice 1)

    • Zampa posteriore sinistra (indice 2)

    • Zampa posteriore destra (indice 3)

    Ogni coordinata ha tre valori:

    • X: posizione avanti/indietro della punta della zampa

    • Y: posizione sinistra/destra della punta della zampa

    • Z: posizione su/giù (più negativo = più in alto)

    # Una posizione eretta per tutte e quattro le zampe
    [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]]
    
  4. Riproduzione di una sequenza di posizioni

    La maggior parte delle azioni è costruita da un elenco di fotogrammi di coordinate. Il metodo do_step() interpola dolcemente i servi dalla posizione corrente alla posizione obiettivo.

    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)
    

    Il secondo argomento di do_step() è la velocità (più alto = più veloce). I valori tipici vanno da 40 (lento) a 80 (veloce).

  5. Azioni integrate vs. personalizzate

    Alcune funzioni utilizzano azioni integrate tramite do_action():

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

    Altre costruiscono posizioni manualmente con do_step(), dandoti pieno controllo sulla 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)
    

    Il movimento di saluto alterna la zampa anteriore destra tra due posizioni estreme, creando un gesto di saluto.

  6. Aggiungere pause tra i movimenti

    La funzione sleep() inserisce pause tra le fasi di movimento. È utile per azioni multifase come 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)
    

    Le pause permettono a ogni fase di completarsi visivamente prima che inizi la successiva.

  7. Uso di move_body_absolute() per il movimento circolare

    La funzione warm_up() dimostra move_body_absolute(), che sposta il centro del corpo rispetto ai piedi:

    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))
    ...
    

    Percorrendo punti su un cerchio (usando valori seno/coseno), il robot esegue un’oscillazione circolare del corpo — un esercizio di riscaldamento che scioglie tutte le articolazioni.

  8. Uscita sicura

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

    Indipendentemente da come il programma termina (Ctrl+C o errore), il blocco finally assicura che il robot torni in una posizione seduta sicura.