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