
Guide du débutant sur la robotique avec Python
Introduction
qui peut effectuer des tâches et prendre des décisions en reproduisant ou en remplaçant les actions humaines. Robotique est le domaine scientifique axé sur la conception et la construction de robots. Il s’agit d’une combinaison multidisciplinaire de :
- Génie électrique pour capteurs et actionneurs. Capteurs recueillir des données sur l’environnement, convertissant les propriétés physiques en signaux électriques (comme nos 5 sens). Actionneurs convertir ces signaux en actions ou mouvements physiques (comme nos muscles).
- Génie mécanique pour la conception et le mouvement de la structure physique.
- L’informatique pour les logiciels et les algorithmes d’IA.
Actuellement, ROS (Système d’exploitation du robot) est le framework principal de la robotique qui gère toutes les différentes parties d’un robot (capteurs, moteurs, contrôleurs, caméras…), où tous les composants échangent des données de manière modulaire. Le ROS Le framework est destiné aux vrais prototypes de robots et peut être utilisé à la fois avec Python et C++. Compte tenu de sa popularité, de nombreuses bibliothèques sont construites sur ROScomme Belvédèrele simulateur 3D le plus avancé.
Depuis Belvédère est assez compliqué, on peut quand même apprendre les bases de la robotique et construire des simulations conviviales en dehors du ROS écosystème. Les principales bibliothèques Python sont :
- PyBullet (débutants) – idéal pour expérimenter avec l’URDF (Unified Robot Description Format), qui est le schéma XML permettant de décrire les corps, les pièces et la géométrie des robots.
- Bots Web (intermédiaire) — la physique est plus précise, ce qui permet de construire des simulations plus complexes.
- MuJoCo (avancé) — simulateur du monde réel, il est utilisé pour des expériences de recherche. OpenAI RoboGYM la bibliothèque est construite sur MuJoCo.

Puisqu’il s’agit d’un tutoriel destiné aux débutants, je vais vous montrer comment créer des simulations 3D simples avec PyBullet. Je présenterai du code Python utile qui peut être facilement appliqué dans d’autres cas similaires (il suffit de copier, coller, exécuter) et de parcourir chaque ligne de code avec des commentaires afin que vous puissiez reproduire cet exemple.
Installation
PyBullet est le simulateur physique le plus convivial pour les jeux, les effets visuels, la robotique et l’apprentissage par renforcement. Vous pouvez facilement l’installer avec l’une des commandes suivantes (si pépin échoue, conda devrait certainement fonctionner) :
pip install pybullet
conda install -c conda-forge pybullet
Vous pouvez courir PyBullet en deux modes principaux :
p.GUI→ ouvre une fenêtre et affiche la simulation en temps réel.p.DIRECT→ pas de mode graphique, utilisé pour les scripts.
import pybullet as p
p.connect(p.GUI) #or p.connect(p.DIRECT)

Puisqu’il s’agit d’un simulateur physique, la première chose à faire est de configurer pesanteur:
p.resetSimulation()
p.setGravity(gravX=0, gravY=0, gravZ=-9.8)
Définit le vecteur de gravité global pour la simulation. « -9,8 » sur l’axe z signifie une accélération de 9,8 m/s^2 vers le bastout comme sur Terre. Sans cela, votre robot et votre avion flotteraient en apesanteur, tout comme dans l’espace.
Fichier URDF
Si le robot était un corps humain, URDF déposer serait le squelette qui définit sa structure physique. C’est écrit en XML, et c’est essentiellement le plan de la machine, définissant à quoi ressemble votre robot et comment il se déplace.
Je vais montrer comment créer un cubes simplesqui est l’équivalent 3D de print(« Bonjour tout le monde »).
urdf_string = """"
<robot name="cube_urdf">
<link name="cube_link">
<visual>
<geometry>
<box size="0.5 0.5 0.5"/> <!-- 50 cm cube -->
</geometry>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.5 0.5 0.5"/>
</geometry>
</collision>
<inertial>
<mass value="1.0"/>
<inertia ixx="0.0001" iyy="0.0001" izz="0.0001"
ixy="0.0" ixz="0.0" iyz="0.0"/>
</inertial>
</link>
</robot>
"""
Vous pouvez soit enregistrer le code XLM sous forme de fichier URDF, soit l’utiliser comme chaîne.
import pybullet as p
import tempfile
## setup
p.connect(p.GUI)
p.resetSimulation()
p.setGravity(gravX=0, gravY=0, gravZ=-9.8)
## create a temporary URDF file in memory
with tempfile.NamedTemporaryFile(suffix=".urdf", mode="w", delete=False) as f:
f.write(urdf_string)
urdf_file = f.name
## load URDF
p.loadURDF(fileName=urdf_file, basePosition=[0,0,1])
## render simulation
for _ in range(240):
p.stepSimulation()

Veuillez noter que la boucle s’est déroulée en 240 étapes. Pourquoi 240 ? Il s’agit d’un pas de temps fixe couramment utilisé dans le développement de jeux vidéo pour une expérience fluide et réactive sans surcharger le processeur. 60 FPS (images par seconde) avec 1 image affichée tous les 1/60 de seconde, ce qui signifie qu’une étape physique de 1/240 secondes fournit 4 mises à jour physiques pour chaque image rendue.
Dans le code précédent, j’ai rendu le cube avec p.stepSimulation(). Cela signifie que la simulation n’est pas en temps réel et que vous contrôlez quand la prochaine étape physique aura lieu. Alternativement, vous pouvez utiliser temps de sommeil pour le lier à l’horloge du monde réel.
import time
## render simulation
for _ in range(240):
p.stepSimulation() #add a physics step (CPU speed = 0.1 second)
time.sleep(1/240) #slow down to real-time (240 steps × 1/240 second sleep = 1 second)

À l’avenir, le code XML pour les robots deviendra beaucoup plus compliqué. Heureusement, PyBullet est livré avec une collection de fichiers URDF prédéfinis. Vous pouvez facilement charger le cube par défaut sans créer le XML correspondant.
import pybullet_data
p.setAdditionalSearchPath(path=pybullet_data.getDataPath())
p.loadURDF(fileName="cube.urdf", basePosition=[0,0,1])
À la base, un fichier URDF définit deux choses principales : links et articulations. Les liens sont la partie solide des robots (comme nos os), et une articulation est la connexion entre deux liens rigides (comme nos muscles). Sans articulations, votre robot ne serait qu’une statue, mais avec des articulations, il devient une machine animée et utile.
En un mot, chaque robot est un arbre de liens reliés par des articulations. Chaque articulation peut être fixe (pas de mouvement) ou rotative (« articulation révolutée ») et coulissante (« articulation prismatique »). Vous devez donc connaître le robot que vous utilisez.
Faisons un exemple avec le célèbre robot R2D2 de Star Wars.

Articulations
Cette fois, nous devons importer un avion ainsi afin de créer un terrain pour le robot. Sans avion, les objets n’auraient pas de surface avec laquelle entrer en collision et tomberaient indéfiniment.
## setup
p.connect(p.GUI)
p.resetSimulation()
p.setGravity(gravX=0, gravY=0, gravZ=-9.8)
p.setAdditionalSearchPath(path=pybullet_data.getDataPath())
## load URDF
plane = p.loadURDF("plane.urdf")
robo = p.loadURDF(fileName="r2d2.urdf", basePosition=[0,0,0.1])
## render simulation
for _ in range(240):
p.stepSimulation()
time.sleep(1/240)
p.disconnect()

Avant d’utiliser le robot, nous devons comprendre ses composants. PyBullet a standardisé la structure de l’information afin que chaque robot que vous importez soit toujours défini par le même 17 attributs universels. Puisque je veux juste exécuter un script, je vais me connecter au serveur physique sans l’interface graphique (p.DIRECT). La fonction principale pour analyser une articulation est p.getJointInfo().
p.connect(p.DIRECT)
dic_info = {
0:"joint Index", #starts at 0
1:"joint Name",
2:"joint Type", #0=revolute (rotational), 1=prismatic (sliding), 4=fixed
3:"state vectorIndex",
4:"velocity vectorIndex",
5:"flags", #nvm always 0
6:"joint Damping",
7:"joint Friction", #coefficient
8:"joint lowerLimit", #min angle
9:"joint upperLimit", #max angle
10:"joint maxForce", #max force allowed
11:"joint maxVelocity", #max speed
12:"link Name", #child link connected to this joint
13:"joint Axis",
14:"parent FramePos", #position
15:"parent FrameOrn", #orientation
16:"parent Index" #−1 = base
}
for i in range(p.getNumJoints(bodyUniqueId=robo)):
print(f"--- JOINT {i} ---")
joint_info = p.getJointInfo(bodyUniqueId=robo, jointIndex=i)
print({dic_info[k]:joint_info[k] for k in dic_info.keys()})

Chaque articulation, qu’il s’agisse d’une roue, d’un coude ou d’une pince, doit présenter ces mêmes caractéristiques. Le code ci-dessus montre que R2D2 possède 15 articulations. Analysons le premier, appelé « base vers jambe droite » :
- Le type de joint est 4, ce qui signifie qu’il ne bouge pas. Le lien parent est -1, ce qui signifie qu’il est connecté au basela partie racine du robot (comme la colonne vertébrale de notre squelette). Pour R2D2, la base est le corps cylindrique principal, ce gros canon bleu et blanc.
- Le nom du lien est « jambe droite », on comprend donc que cette articulation relie la base du robot à la jambe droite, mais elle n’est pas motorisée. Cela est confirmé par axe articulaire, dumping communet frottement des articulations étant tous des zéros.
- Position du cadre parent et orientation définir où la jambe droite est attachée à la base.
Links
En revanche, pour analyser les liens (les segments du corps physique), il faut parcourir les articulations pour en extraire le nom du lien. Ensuite, vous pouvez utiliser deux fonctions principales : p.getDynamicsInfo() comprendre les propriétés physiques du lien, et p.getLinkState() connaître son état spatial.
p.connect(p.DIRECT)
for i in range(p.getNumJoints(robo)):
link_name = p.getJointInfo(robo, i)[12].decode('utf-8') #field 12="link Name"
dyn = p.getDynamicsInfo(robo, i)
pos, orn, *_ = p.getLinkState(robo, i)
dic_info = {"Mass":dyn[0], "Friction":dyn[1], "Position":pos, "Orientation":orn}
print(f"--- LINK {i}: {link_name} ---")
print(dic_info)

Analysons la première, la « jambe droite ». Le masse de 10 kg contribue à la gravité et à l’inertie, tandis que le friction affecte la façon dont il glisse au contact du sol. Le orientation (0,707=péché(45°)/cos(45°)) et position indiquent que le lien de la jambe droite est une pièce pleine, légèrement vers l’avant (5 cm), inclinée à 90° par rapport à la base.
Mouvements
Jetons un coup d’œil à une articulation qui peut réellement bouger.
Par exemple, l’articulation 2 est la roue avant droite. C’est un joint de type = 0, donc il tourne. Cette articulation relie la jambe droite (lien indice 1) à la roue avant droite : base_link → right_leg → right_front_wheel. L’axe commun est (0,0,1), nous savons donc que la roue tourne autour de l’axe z. Les limites (inférieure=0, supérieure=-1) indiquent que la roue peut tourner à l’infini, ce qui est normal pour les rotors.
Nous pouvons facilement déplacer cette articulation. La commande principale pour contrôler les actionneurs de votre robot est p.setJointMotorControl2()il permet de contrôler la force, la vitesse et la position d’une articulation. Dans ce cas, je veux faire tourner la roue, donc je vais appliquer une force pour amener progressivement la vitesse de zéro à une vitesse cible, puis la maintenir en équilibrant la force appliquée et les forces résistives (c’est-à-dire friction, amortissement, gravité).
p.setJointMotorControl2(bodyUniqueId=robo, jointIndex=2,
controlMode=p.VELOCITY_CONTROL,
targetVelocity=10, force=5)
Maintenant, si nous appliquons la même force à toutes les 4 rouesnous ferons avancer notre petit robot. D’après l’analyse effectuée précédemment, nous savons que les articulations de la roue sont les numéros 2 et 3 (côté droit) et les numéros 6 et 7 (côté gauche).

Considérant cela, je vais d’abord faire tourner R2D2 en tournant d’un seul côté, puis appliquer une force sur chaque roue en même temps pour la faire avancer.
import pybullet as p
import pybullet_data
import time
## setup
p.connect(p.GUI)
p.resetSimulation()
p.setGravity(gravX=0, gravY=0, gravZ=-9.8)
p.setAdditionalSearchPath(path=pybullet_data.getDataPath())
## load URDF
plane = p.loadURDF("plane.urdf")
robo = p.loadURDF(fileName="r2d2.urdf", basePosition=[0,0,0.1])
## settle down
for _ in range(240):
p.stepSimulation()
right_wheels = [2,3]
left_wheels = [6,7]
### first turn
for _ in range(240):
for j in right_wheels:
p.setJointMotorControl2(bodyUniqueId=robo, jointIndex=j,
controlMode=p.VELOCITY_CONTROL,
targetVelocity=-100, force=50)
for j in left_wheels:
p.setJointMotorControl2(bodyUniqueId=robo, jointIndex=j,
controlMode=p.VELOCITY_CONTROL,
targetVelocity=100, force=50)
p.stepSimulation()
time.sleep(1/240)
### then move forward
for _ in range(500):
for j in right_wheels + left_wheels:
p.setJointMotorControl2(bodyUniqueId=robo, jointIndex=j,
controlMode=p.VELOCITY_CONTROL,
targetVelocity=-100, force=10)
p.stepSimulation()
time.sleep(1/240)
p.disconnect()

Veuillez noter que chaque robot a une masse (poids) différente, donc les mouvements peuvent être différents en fonction de la physique de la simulation (c’est-à-dire la gravité). Vous pouvez jouer et essayer différentes forces et vitesses jusqu’à ce que vous trouviez le résultat souhaité.

Conclusion
Cet article a été un tutoriel pour présenter PyBullet et comment créer des simulations 3D très basiques pour la robotique. Nous avons appris à importer des objets URDF et à analyser les articulations et les liens. Nous avons également joué avec le célèbre robot R2D2. De nouveaux tutoriels avec des robots plus avancés arriveront.
Code complet pour cet article : GitHub
J’espère que vous l’avez apprécié ! N’hésitez pas à me contacter pour des questions et des commentaires ou simplement pour partager vos projets intéressants.
👉 Connectons-nous 👈

(Toutes les images sont de l’auteur, sauf indication contraire noté)



