A Beginner's Guide to Robotics with Python

– Nombeke
that can perform tasks and make decisions by repeating or replacing human action. Robots Is the field of science focused on the design and construction of robots. It is a multididinlinary combination of:
- Electrical engineering For sensors and operators. Sensors collect data from nature, converting physical properties into electrical signals (like our 5 senses). Actuators convert these signals into physical actions or movements (like our muscles).
- mechanical Engineering the design and movement of the body structure.
- Computer Science With AI software and algorithms.
Currently, It's cool (Robot app) The main framework of robots manages all the different parts of the robot (sensors, motors, controllers, cameras …), where all parts exchange information in a common way. This page It's cool The framework is designed for real robot prototypes, and can be implemented with python and C++. Given its popularity, there are many libraries built over the It's coollike GazeboThe most advanced 3D simulator.
Ever since Gazebo it is quite complex, one can still learn the basics of robots and build a user friendly mask apart from It's cool EcoSystem. The main Python libraries are:
- Pybullet .
- Webrots (Medium) – The physics are more accurate, so it can create more complex puzzles.
- Mujoco (Advanced) – Real world simulator, used for research grade testing. Opelai's History the library was built over Mujoco.

Since this is a tutorial for beginners, I will show you how Create a simple 3D overlay with Pybullet. I will present some useful Python code that can be easily used in other similar cases (just copy, paste, run) and go) go through every line of code to repeat and repeat and repeat and repeat and repeat and repeat and repeat this example.
Timing
Pybullet Is an easy-to-use physics for game physics, visual effects, robotics, and learning and reinforcement. You can easily install it with one of the following commands (if peach failed, listen they should definitely work):
pip install pybullet
conda install -c conda-forge pybullet
You can run Pybullet in two main ways:
p.GUI→ Opens a window and shows the overlay in real time.p.DIRECT→ No graphics mode, used for scripts.
import pybullet as p
p.connect(p.GUI) #or p.connect(p.DIRECT)

Since this is a physics model, the first thing to do is set it up weight:
p.resetSimulation()
p.setGravity(gravX=0, gravY=0, gravZ=-9.8)
Sets the Global Gravity vector to zero. “-9.8” on the Z-axis means the acceleration of 9.8 m / s ^ 2 Down, as in earth. Without this, your robot and planet would float in zero-gravity, like in space.
Urdf file
If a robot were a human body, Urdf file it can be a skeleton that describes its physical structure. It's written in XML, and basically A mechanical Blueprint, describes what your robot looks like and how it moves.
I will show you how to build a A simple cubewhich is 3D equivalent Print (“Hello World”).
urdf_string = """"
"""
You can save the XLM code as a URDF file or run as a string.
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()

Please note that the loop was run for 240 steps. Why 240? A time limiter that is widely used in videogame development for a smooth and responsive experience without hogging the CPU. 60 FPS (frames per second) with 1 frame displayed every 1/60 second, which means a physics step of 1/40 seconds.
In the previous code, I gave the cube with p.stepSimulation(). It means that the unveiling is not in real time and you control when the next step of physics happens. Alternatively, you can use Sleep Time real world clock binding.
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)

Going forward, XML code for robots will get more complex. Fortunately, Pybullet It comes with a set of preset Urdf files. You can easily load a default cube without creating XML for it.
import pybullet_data
p.setAdditionalSearchPath(path=pybullet_data.getDataPath())
p.loadURDF(fileName="cube.urdf", basePosition=[0,0,1])
At its core, a URDF file defines two main things: Others and they are members. Joints are the rigid part of robots (like our bones), and joints are connections between two rigid links (like our muscles). Without joints, your robot would be just a picture, but with joints it becomes a moving and purposeful machine.
In short, all robots are a tree of links connected by joints. Each joint can be fixed (no movement) or rotating (“joint joint”) and slide (“Prismatic Joint)). Therefore, you need to know the robot you are using.
Let's make an example with the famous Robot R2D2 from star wars.

They are members
In this case, it should Import the plane and to build a robot ground. Without the plane, things would have no place to meet and just appear forever.
## 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()

Before using a robot, we must understand its parts. Pybullet it deserves an information structure so that all importing robots will always be defined in the same way 17 Universal Attributes. Since I want to run the script, I will connect to the physics server without the interface (p.DIRECT). The main task is to analyze the convergence 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()})

Every compound, it doesn't matter if it's a wheel, an elbow, or a gripper, it should reveal those same features. The code above shows that R2D2 has 15 joints. Let's analyze the first one, called “Base to Right-Leg”:
- This page joint type is 4, which means it doesn't go. This page Parent Link is -1, which means it is connected to backgroundThe root part of the robot (like our skin spine). With R2D2, the base is the main body of the cylinder, that big blue and white lump.
- This page Link Name “Right leg”, so we understand that the assembly of this connects the base of the robot with the right leg, but it is not well done. That is confirmed by Joint Axis, Joint disposalagain collective conflict to have all the events.
- Parental Position of Parents and understanding Explain where the right leg is attached to the base.
Others
On the other hand, in order to analyze the links (parts of the physical body), one has to loosen the joints to extract the name of the link. After that, you can use two main functions: p.getDynamicsInfo() understanding the visual properties of the link, too p.getLinkState() knowing its location.
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)

Let's analyze the first one, the “right leg”. This page much more of 10 kg has an impact on the wall and -nertia, while bumping into each other it affects how many slides there are when interacting with the world. This page understanding (0.707 =Sin (45 °) / cos (45 °)) And stop Show that the REGHT-REG link is a solid piece, forward (5cm), tilted 90 ° relative to the base.
Movement
Let's have a look at the meeting that can go.
With ISTance, the Joint 2 is the ideal front wheel. Type = 0 to match, so it rotates. This joint connects the right leg (reference link 1) to the right wheel before the left: base_link → right_leg → right_right_. The coordinate axis is (0,0,1), so we know that the wheels revolve around the axis. Limits (low = 0, high = -1) Show that the wheel can force indefinitely, typical for rotors.
We can easily Submit this compilation. A great command to control the operators on your robot p.setJointMotorControl2()allows to control the force, velocity, and position of the combination. In this case, I want to make the wheel go up, so I will apply forces to gradually bring the velocity from zero to the target velocity, and then maintain it by balancing the force and resistance (meaning confusion, pull, pull, pull down).
p.setJointMotorControl2(bodyUniqueId=robo, jointIndex=2,
controlMode=p.VELOCITY_CONTROL,
targetVelocity=10, force=5)
Now, if we use the same force all 4 wheelswe will make our little robot move forward. From the previous analysis, we know that the wheel joints are number 2 and 3 (right side), and number 6 and 7 (left side).

Looking at that, I would first make R2DD2 turn by turning only one side, then apply power to all wheels at the same time to make it go forward.
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()

Please be aware that all robots have a different mass (weight) so the movement can vary based on the physics of the simulation (IE Gravity). You can play and try different power and velocity until you get the desired result.

Lasting
This article has been a study in it introducing pybullet and how to create basic 3D renderings For robots. We learned how to import Urdf objects and how to analyze joints and links. We also played with the famous Robot R2D2. A new tutorial on advanced robots is coming.
The complete code for this article: A certain medicine kiki
I hope you enjoyed it! Feel free to contact me with questions and feedback or just to share your interesting projects.
👉 Let's get in touch 👈

(All photos are by the author except this one noted)



