.. note::
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 [|link_sf_facebook|] e unisciti subito!
.. _py_action_gallery:
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**
.. raw:: html
.. code-block::
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**
.. note::
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.
.. raw:: html
.. code-block:: python
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?**
#. All'avvio del programma, viene creato un dizionario delle azioni
disponibili e stampato un menu numerato.
.. code-block:: python
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.
#. Ciclo del menu interattivo
.. code-block:: python
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.
#. 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)
.. code-block:: python
# Una posizione eretta per tutte e quattro le zampe
[[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]]
#. 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.
.. code-block:: python
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).
#. Azioni integrate vs. personalizzate
Alcune funzioni utilizzano azioni integrate tramite ``do_action()``:
.. code-block:: python
def sit(spider):
spider.do_action('sit', speed=40)
Altre costruiscono posizioni manualmente con ``do_step()``, dandoti pieno
controllo sulla postura del robot.
.. code-block:: python
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.
#. Aggiungere pause tra i movimenti
La funzione ``sleep()`` inserisce pause tra le fasi di movimento. È utile
per azioni multifase come ``fighting()`` o ``nod()``:
.. code-block:: python
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.
#. 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:
.. code-block:: python
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.
#. Uscita sicura
.. code-block:: python
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.