Step 1
The equations of motion
Predict what torques will do to the whole arm with M(q) q̈ + h = τ, then watch the real arm follow your prediction.
Builds on Mass, inertia & F = ma, from the free Foundations.
One equation for the whole arm
One joint on its own obeys (Foundations: Mass, inertia & F = ma). With all four joints free, each joint's motion depends on the others, and the arm obeys one vector equation, its equations of motion:
- , , are the four joint angles (rad), velocities (rad/s) and accelerations (rad/s²), ordered [base, shoulder, elbow, wrist]; holds the four motor torques (N·m).
- is the 4×4 mass matrix (kg·m²). Its diagonal holds each joint's inertia, the from , and it changes with the pose. The off-diagonal entries couple the joints: a torque on the shoulder also swings the elbow.
- holds the bias torques: gravity , plus the Coriolis and centrifugal torques that appear when joints move, the way a spinning base flings the forearm outwards.
Forward dynamics
Solve the equation for the accelerations and you can predict the motion:
np.linalg.solve(M, b) finds with without inverting .
| Call | Returns |
|---|---|
arm.mass_matrix(q) | , a 4×4 array |
arm.bias_torques(q, qd) | , 4 torques |
arm.gravity_torques(q) | , 4 torques |
Pass q and qd explicitly: without them these read the live arm, and the grader calls your function on other states.
The program
The arm starts folded, its motors cancelling gravity. It gets a kick on the base, shoulder and elbow for 0.2 s, then the same kick backwards. First your model predicts the next 0.6 s, stepping and every = 2 ms, and draws the hand's path in yellow. Then the real arm runs, in blue, and Plots compares the angles. Finally it prints the diagonal of folded and unfolded: which joints got heavier, and why?
Your task
Write forward_dynamics(q, qd, tau). It must match the simulator on 8 states, and your prediction must stay within 0.5° of the real arm for the whole 0.6 s.