Forward Kinematics
DH Params:
1# Denavit-Hartenberg (DH) Parameters2# 4 parameters describe the transformation from link i-1 to link i.34class DH_Param:5 def __init__(self, theta, d, a, alpha):6 self.theta = theta # Joint angle (rotation about Z)7 self.d = d # Link offset (translation along Z)8 self.a = a # Link length (translation along X)9 self.alpha = alpha # Link twist (rotation about X)
Denavit-Hartenberg parameters provide a standard way to map coordinate frames between robot links. Only 4 parameters (theta, d, a, alpha) are needed to describe the transformation from one joint to the next.
DH Matrix:
1# Constructing the DH Transformation Matrix2import numpy as np34def dh_matrix(theta, d, a, alpha):5 """Returns 4x4 homogenous transform matrix."""6 c_t, s_t = np.cos(theta), np.sin(theta)7 c_a, s_a = np.cos(alpha), np.sin(alpha)89 return np.array([10 [c_t, -s_t*c_a, s_t*s_a, a*c_t],11 [s_t, c_t*c_a, -c_t*s_a, a*s_t],12 [0, s_a, c_a, d],13 [0, 0, 0, 1]14 ])
The 4 DH parameters are plugged into a standard 4x4 homogenous transformation matrix. This single matrix encapsulates all the necessary rotations and translations to move from link i-1 to link i.
Matrix Multiplication:
1# Forward Kinematics Transform Concatenation2def calculate_forward_kinematics(dh_params, joint_angles):3 """Computes poses for all links in the chain."""4 T_curr = np.eye(4)5 poses = [T_curr]67 for i, p in enumerate(dh_params):8 # Update theta with current joint angle9 theta_i = p.theta + joint_angles[i]1011 # Get local transform for this link12 T_local = dh_matrix(theta_i, p.d, p.a, p.alpha)1314 # Multiply with accumulated transform15 T_curr = np.dot(T_curr, T_local)16 poses.append(T_curr)1718 return poses
To find the position of any link in the world space, we multiply the local DH matrices sequentially from the base. This process is called Forward Kinematics (FK).
Axis Extraction:
1# Visualizing Joint Axes2def get_joint_axis(T_matrix):3 """Extract the Z-axis vector from the transform matrix."""4 # In DH convention, the Z-axis is the axis of rotation5 # It is stored in the 3rd column of the rotation matrix (index 2)6 z_dir = T_matrix[0:3, 2]7 pos = T_matrix[0:3, 3]8 return pos, z_dir
In the Denavit-Hartenberg convention, the Z-axis of the local coordinate frame is always aligned with the axis of rotation (or translation for prismatic joints). Extracting the Z-column from the transform matrix gives the axis direction in world space.
TCP Offset:
1# TCP (Tool Center Point) Configuration2# The end effector has its own local offset from the final joint.34def get_tcp_pose(final_joint_matrix, tcp_offset_vector):5 """Calculate the pose of the tool center point."""6 import numpy as np78 # Create translation matrix for the TCP offset9 T_tcp = np.eye(4)10 T_tcp[0:3, 3] = tcp_offset_vector1112 # Final pose is joint matrix multiplied by tool offset matrix13 return np.dot(final_joint_matrix, T_tcp)
The Tool Center Point (TCP) is the functional tip of the robot (e.g., the nozzle of an extruder or the jaws of a gripper). It is defined as a fixed offset from the last joint's coordinate frame.
Workspace Generation:
1# Configuration Space Sweep2def generate_workspace(kinematics_fn, joint_limits, resolution):3 """Samples the reachable workspace of the robot."""4 workspace_points = []56 # Nested loops sweep through all possible joint angles7 for j1 in range(joint_limits[0].min, joint_limits[0].max, resolution):8 for j2 in range(joint_limits[1].min, joint_limits[1].max, resolution):9 # Calculate forward kinematics for this configuration10 tcp_pose = kinematics_fn([j1, j2])11 workspace_points.append(tcp_pose.position)1213 return workspace_points
By sweeping through all possible joint angle combinations within their limits, we can map out the entire reachable workspace of the robot arm. This is a brute-force application of Forward Kinematics.
Control Loop:
t. 2. Re-evaluate the Forward Kinematics chain. 3. Apply resulting transformation matrices to 3D meshes.1# Real-time FK Control Loop2def update_robot(time_t):3 """Animate joint angles over time."""4 import math56 # Sine wave driven joints7 j1 = math.sin(time_t * 1.5) * math.pi/28 j2 = math.cos(time_t * 2.0) * math.pi/39 j3 = math.sin(time_t * 0.5) * math.pi/41011 # Compute FK and update renderer12 poses = calculate_forward_kinematics(dh_params, [j1, j2, j3])13 render_robot(poses)
In a dynamic simulation, joint angles are updated continuously over time. The forward kinematics algorithm runs every frame, recomputing the entire pose chain to animate the robot smoothly.
Related Concepts
Implicit CSG union, intersection, subtraction, smooth booleans, chamfers, and fillets.
Exponential and polynomial smooth-min operators, attribute blending, shape morphing, and organic fusion.
Sphere tracing, SDF surface normals, soft penumbra shadows, ambient occlusion, and volumetric fog.