.. note::
Bonjour, bienvenue dans la communauté des passionnés de Raspberry Pi, Arduino et ESP32 sur Facebook ! Plongez dans l'univers du Raspberry Pi, Arduino et ESP32 avec d'autres passionnés.
**Pourquoi rejoindre ?**
- **Support d'experts** : Résolvez les problèmes post-vente et les défis techniques avec l'aide de notre communauté et de notre équipe.
- **Apprendre et partager** : Échangez des astuces et des tutoriels pour améliorer vos compétences.
- **Aperçus exclusifs** : Accédez en avant-première aux annonces de nouveaux produits et aperçus exclusifs.
- **Réductions spéciales** : Profitez de réductions exclusives sur nos produits les plus récents.
- **Promotions festives et concours** : Participez à des concours et promotions spéciales.
👉 Prêt à explorer et à créer avec nous ? Cliquez sur [|link_sf_facebook|] et rejoignez-nous dès aujourd'hui !
.. _py_action_gallery:
14. Galerie d'actions
====================================
Cet exemple fournit un menu interactif qui vous permet de déclencher une
variété d'actions préprogrammées pour PiCrawler, notamment saluer, serrer la
main, combattre, hocher la tête, faire des pompes et plus encore.
**Exécuter le code**
.. raw:: html
.. code-block::
cd ~/picrawler/examples
sudo python3 14_action_gallery.py
Après avoir exécuté le programme, une liste numérotée des actions disponibles
s'affiche dans le terminal. Tapez le numéro de l'action souhaitée, puis
appuyez sur **Entrée** pour l'exécuter. Appuyez à nouveau sur **Entrée** pour
répéter la dernière action.
Si **Ctrl+C** est pressé, le programme se termine en toute sécurité et le
robot retourne en position assise.
**Code**
.. note::
Vous pouvez **Modifier/Réinitialiser/Copier/Exécuter/Arrêter** le code
ci-dessous. Mais avant cela, vous devez aller dans le chemin du code source
comme ``picrawler\examples``. Après avoir modifié le code, vous pouvez
l'exécuter directement pour voir l'effet.
.. 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)
**Comment ça fonctionne ?**
#. Au démarrage du programme, il construit un dictionnaire des actions
disponibles et affiche un menu numéroté.
.. 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}')
Chaque clé dans ``actions_dict`` est un nom lisible et chaque valeur est
une fonction. Ce modèle facilite la recherche et l'appel de la bonne
fonction lorsque l'utilisateur entre un numéro.
#. Boucle de menu interactive
.. 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)
La boucle principale attend la saisie de l'utilisateur :
- Entrez un numéro pour sélectionner et exécuter immédiatement une action.
- Appuyez sur **Entrée** (saisie vide) pour répéter la dernière action.
- Appuyez sur **Ctrl+C** pour quitter.
#. Qu'est-ce qu'un pas de coordonnées ?
Chaque posture est définie comme une liste de quatre coordonnées de pattes
au format ``[[x, y, z], [x, y, z], [x, y, z], [x, y, z]]``, correspondant à :
- Patte avant droite (index 0)
- Patte avant gauche (index 1)
- Patte arrière gauche (index 2)
- Patte arrière droite (index 3)
Chaque coordonnée a trois valeurs :
- **X** : position avant/arrière de l'extrémité de la patte
- **Y** : position gauche/droite de l'extrémité de la patte
- **Z** : position haut/bas (plus négatif = plus haut)
.. code-block:: python
# Une posture debout pour les quatre pattes
[[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]]
#. Jouer une séquence de postures
La plupart des actions sont construites à partir d'une liste de trames de
coordonnées. La méthode ``do_step()`` interpole en douceur les servos de
la posture actuelle à la posture cible.
.. 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)
Le deuxième argument de ``do_step()`` est la **vitesse** (plus élevé =
plus rapide). Les valeurs typiques vont de 40 (lent) à 80 (rapide).
#. Actions intégrées vs. personnalisées
Certaines fonctions utilisent des actions intégrées via ``do_action()`` :
.. code-block:: python
def sit(spider):
spider.do_action('sit', speed=40)
D'autres construisent des postures manuellement avec ``do_step()``, vous
donnant un contrôle total sur la posture du 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)
Le mouvement de salut alterne la patte avant droite entre deux positions
extrêmes, créant un geste de salut.
#. Ajouter des délais entre les mouvements
La fonction ``sleep()`` insère des pauses entre les phases de mouvement.
C'est utile pour les actions multi-phases comme ``fighting()`` ou
``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)
Les pauses permettent à chaque phase de se terminer visuellement avant que
la suivante ne commence.
#. Utilisation de ``move_body_absolute()`` pour un mouvement circulaire
La fonction ``warm_up()`` démontre ``move_body_absolute()``, qui déplace
le centre du corps par rapport aux pieds :
.. 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))
...
En parcourant des points sur un cercle (en utilisant des valeurs sinus/
cosinus), le robot effectue un balancement corporel circulaire — un
exercice d'échauffement qui assouplit toutes les articulations.
#. Sortie sécurisée
.. code-block:: python
finally:
my_spider.do_action("sit", speed=40)
sleep(.1)
Peu importe comment le programme se termine (Ctrl+C ou erreur), le bloc
``finally`` garantit que le robot retourne en position assise sécurisée.