Kinematics API Reference
This page documents ManipulaPy.kinematics, the module for manipulator kinematics computations.
Tip
For conceptual explanations, see Kinematics User Guide.
SerialManipulator Class
- class ManipulaPy.kinematics.SerialManipulator(M_list, omega_list, r_list=None, b_list=None, S_list=None, B_list=None, G_list=None, joint_limits=None)[source]
Bases:
objectMain class for serial manipulator kinematics using Product of Exponentials (PoE) formulation.
Constructor
- Parameters:
- __init__(M_list, omega_list, r_list=None, b_list=None, S_list=None, B_list=None, G_list=None, joint_limits=None)[source]
Initialize the class with the given parameters.
- Parameters:
M_list (list) – A list of M values.
omega_list (list) – A list of omega values.
r_list (list, optional) – A list of r values. Defaults to None.
b_list (list, optional) – A list of b values. Defaults to None.
S_list (list, optional) – A list of S values. Defaults to None.
B_list (list, optional) – A list of B values. Defaults to None.
G_list (list, optional) – A list of G values. Defaults to None.
joint_limits (list, optional) – A list of joint limits. Defaults to None.
- Return type:
None
Parameters:
M_list (numpy.ndarray) – Home configuration matrix (4×4)
omega_list (numpy.ndarray) – Joint rotation axes (3×n)
r_list (numpy.ndarray, optional) – Joint position vectors (3×n)
b_list (numpy.ndarray, optional) – Body frame joint positions (3×n)
S_list (numpy.ndarray, optional) – Space frame screw axes (6×n)
B_list (numpy.ndarray, optional) – Body frame screw axes (6×n)
G_list (numpy.ndarray, optional) – Spatial inertia matrices (6×6×n)
joint_limits (list, optional) – Joint limits [(min, max), …] for each joint
Auto-computation: Missing S_list or B_list computed from omega_list and r_list/b_list.
State Management
- update_state(joint_positions, joint_velocities=None)[source]
Updates the internal state of the manipulator.
- Parameters:
joint_positions (np.ndarray) – Current joint positions.
joint_velocities (np.ndarray, optional) – Current joint velocities. Default is None.
- Return type:
None
Parameters:
joint_positions (array_like) – Current joint positions in radians
joint_velocities (array_like, optional) – Current joint velocities in rad/s
Purpose: Updates internal state for stateful operations.
Forward Kinematics
- forward_kinematics(thetalist, frame='space')[source]
Compute the forward kinematics of a robotic arm using the product of exponentials method.
- Parameters:
thetalist (numpy.ndarray) – A 1D array of joint angles in radians.
frame (str, optional) – The frame in which to compute the forward kinematics. Either ‘space’ or ‘body’.
- Returns:
The 4x4 transformation matrix representing the end-effector’s pose.
- Return type:
Parameters:
thetalist (array_like) – Joint angles in radians
frame (str) – Reference frame: “space” or “body” (default: “space”)
Returns:
T (numpy.ndarray) – 4×4 transformation matrix
Formula (Space): T(θ) = e^{S₁θ₁} e^{S₂θ₂} … e^{Sₙθₙ} M
Formula (Body): T(θ) = M e^{B₁θ₁} e^{B₂θ₂} … e^{Bₙθₙ}
- Example:
>>> T = robot.forward_kinematics([0.1, 0.2, 0.3], frame="space") >>> position = T[:3, 3] # Extract position >>> rotation = T[:3, :3] # Extract rotation matrix
- end_effector_pose(thetalist)[source]
Computes the end-effector’s position and orientation given joint angles.
- Parameters:
thetalist (numpy.ndarray) – A 1D array of joint angles in radians.
- Returns:
A 6x1 vector representing the position and orientation (Euler angles) of the end-effector.
- Return type:
Parameters:
thetalist (array_like) – Joint angles in radians
Returns:
pose (numpy.ndarray) – 6-element vector [x, y, z, roll, pitch, yaw]
Components: Position (meters) + Euler angles (radians)
Velocity Kinematics
- jacobian(thetalist, frame='space')[source]
Calculate the Jacobian matrix for the given joint angles.
- Parameters:
- Returns:
The Jacobian matrix of shape (6, len(thetalist)).
- Return type:
Parameters:
thetalist (array_like) – Joint angles in radians
frame (str) – Reference frame: “space” or “body” (default: “space”)
Returns:
J (numpy.ndarray) – 6×n Jacobian matrix
Structure: J = [J_v; J_ω] where J_v is linear, J_ω is angular velocity Jacobian
Formula (Space): J_s = [Ad_{T₁} S₁, Ad_{T₂} S₂, …, Ad_{Tᵢ} Sᵢ, …]
Formula (Body): J_b = [Ad_{T⁻¹} B₁, Ad_{T⁻¹} B₂, …, Ad_{T⁻¹} Bₙ]
- end_effector_velocity(thetalist, dthetalist, frame='space')[source]
Calculate the end effector velocity given the joint angles and joint velocities.
- Parameters:
- Returns:
The end effector velocity.
- Return type:
Parameters:
thetalist (array_like) – Joint angles in radians
dthetalist (array_like) – Joint velocities in rad/s
frame (str) – Reference frame: “space” or “body” (default: “space”)
Returns:
V (numpy.ndarray) – 6-element twist vector [vx, vy, vz, ωx, ωy, ωz]
Formula: V = J(θ) θ̇
- joint_velocity(thetalist, V_ee, frame='space')[source]
Calculates the joint velocity given the joint positions, end-effector velocity, and frame type.
- Parameters:
- Returns:
The joint velocity.
- Return type:
array-like
Parameters:
thetalist (array_like) – Joint angles in radians
V_ee (array_like) – Desired end-effector velocity twist
frame (str) – Reference frame: “space” or “body” (default: “space”)
Returns:
dthetalist (numpy.ndarray) – Required joint velocities in rad/s
Formula: θ̇ = J⁺(θ) V where J⁺ is Moore-Penrose pseudoinverse
Inverse Kinematics
- iterative_inverse_kinematics(T_desired, thetalist0, eomg=1e-06, ev=1e-06, max_iterations=10000, plot_residuals=False, damping=0.02, step_cap=0.3, png_name='ik_residuals.png', weight_orientation=1.0, weight_position=1.0, adaptive_tuning=False, backtracking=False)[source]
Damped-least-squares iterative IK with joint-limit projection and residual plot saved to file (no interactive window).
Features: - Levenberg-Marquardt style adaptive damping - SVD-robust Jacobian solve for near-singular configs - Stagnation detection with perturbation recovery - Improved line search with multiple scales - Best solution tracking
Parameters:
T_desired (numpy.ndarray) – Desired 4×4 transformation matrix
thetalist0 (array_like) – Initial guess for joint angles
eomg (float) – Rotational error tolerance (default: 1e-9)
ev (float) – Translational error tolerance (default: 1e-9)
max_iterations (int) – Maximum iterations (default: 5000)
plot_residuals (bool) – Plot convergence (default: False)
Returns:
thetalist (numpy.ndarray) – Solution joint angles
success (bool) – Convergence status
num_iterations (int) – Iterations used
Algorithm: Newton-Raphson with Damped Least Squares
Update: θₖ₊₁ = θₖ + α J⁺(θₖ) V_error
Convergence: ||V_trans|| < ev AND ||V_rot|| < eomg
- update_state(joint_positions, joint_velocities=None)[source]
Updates the internal state of the manipulator.
- Parameters:
joint_positions (np.ndarray) – Current joint positions.
joint_velocities (np.ndarray, optional) – Current joint velocities. Default is None.
- Return type:
None
- forward_kinematics(thetalist, frame='space')[source]
Compute the forward kinematics of a robotic arm using the product of exponentials method.
- Parameters:
thetalist (numpy.ndarray) – A 1D array of joint angles in radians.
frame (str, optional) – The frame in which to compute the forward kinematics. Either ‘space’ or ‘body’.
- Returns:
The 4x4 transformation matrix representing the end-effector’s pose.
- Return type:
- end_effector_velocity(thetalist, dthetalist, frame='space')[source]
Calculate the end effector velocity given the joint angles and joint velocities.
- Parameters:
- Returns:
The end effector velocity.
- Return type:
- jacobian(thetalist, frame='space')[source]
Calculate the Jacobian matrix for the given joint angles.
- Parameters:
- Returns:
The Jacobian matrix of shape (6, len(thetalist)).
- Return type:
- iterative_inverse_kinematics(T_desired, thetalist0, eomg=1e-06, ev=1e-06, max_iterations=10000, plot_residuals=False, damping=0.02, step_cap=0.3, png_name='ik_residuals.png', weight_orientation=1.0, weight_position=1.0, adaptive_tuning=False, backtracking=False)[source]
Damped-least-squares iterative IK with joint-limit projection and residual plot saved to file (no interactive window).
Features: - Levenberg-Marquardt style adaptive damping - SVD-robust Jacobian solve for near-singular configs - Stagnation detection with perturbation recovery - Improved line search with multiple scales - Best solution tracking
- smart_inverse_kinematics(T_desired, strategy='workspace_heuristic', theta_current=None, T_current=None, cache=None, eomg=1e-06, ev=1e-06, max_iterations=10000, plot_residuals=False, damping=0.02, step_cap=0.3, png_name='ik_residuals.png', weight_orientation=1.0, weight_position=1.0, adaptive_tuning=True, backtracking=True, auto_fallback=True)[source]
Smart inverse kinematics with intelligent initial guess strategies.
Automatically selects initial guess using various strategies for improved convergence. With auto_fallback=True, tries multiple strategies if first fails.
- Parameters:
T_desired (ndarray[Any, dtype[float64]]) – Target 4x4 transformation matrix
strategy (str) – Initial guess strategy to use: - ‘workspace_heuristic’: Geometric approximation (default, recommended) - ‘extrapolate’: Extrapolate from current config (for trajectories) - ‘cached’: Use nearest cached solution (requires cache parameter) - ‘random’: Random within joint limits - ‘midpoint’: Midpoint of joint limits
theta_current (ndarray[Any, dtype[float64]] | List[float] | None) – Current joint angles (required for ‘extrapolate’)
T_current (ndarray[Any, dtype[float64]] | None) – Current end-effector pose (required for ‘extrapolate’)
cache (Any | None) – IKInitialGuessCache instance (required for ‘cached’)
auto_fallback (bool) – If True, try other strategies if primary fails (default: True)
iterative_inverse_kinematics() (Other args same as) –
eomg (float) –
ev (float) –
max_iterations (int) –
plot_residuals (bool) –
damping (float) –
step_cap (float) –
png_name (str) –
weight_orientation (float) –
weight_position (float) –
adaptive_tuning (bool) –
backtracking (bool) –
- Returns:
Tuple of (theta, success, iterations)
- Return type:
- robust_inverse_kinematics(T_desired, max_attempts=10, eomg=0.002, ev=0.002, max_iterations=5000, verbose=False)[source]
Robust inverse kinematics with adaptive multi-start strategy.
Tries multiple initial guesses and parameter combinations to maximize success rate. Tracks best solution across all attempts.
- Parameters:
T_desired (ndarray[Any, dtype[float64]]) – Target 4x4 transformation matrix
max_attempts (int) – Maximum IK attempts (default: 10)
eomg (float) – Orientation tolerance in radians (default: 2e-3 = 2mrad)
ev (float) – Position tolerance in meters (default: 2e-3 = 2mm)
max_iterations (int) – Max iterations per attempt (default: 5000)
verbose (bool) – Print detailed progress (default: False)
- Returns:
Tuple of (theta, success, total_iterations, winning_strategy)
- Return type:
- joint_velocity(thetalist, V_ee, frame='space')[source]
Calculates the joint velocity given the joint positions, end-effector velocity, and frame type.
- end_effector_pose(thetalist)[source]
Computes the end-effector’s position and orientation given joint angles.
- Parameters:
thetalist (numpy.ndarray) – A 1D array of joint angles in radians.
- Returns:
A 6x1 vector representing the position and orientation (Euler angles) of the end-effector.
- Return type:
- trac_ik(T_desired, theta0=None, timeout=0.2, eomg=0.0001, ev=0.0001, num_restarts=5, use_parallel=False)[source]
TRAC-IK style inverse kinematics solver.
Uses a DLS-first strategy with SQP fallback and diverse initial guesses. Sequential mode (default) avoids Python GIL contention for best results.
- Parameters:
T_desired (ndarray[Any, dtype[float64]]) – Target 4x4 transformation matrix
theta0 (ndarray[Any, dtype[float64]] | List[float] | None) – Initial guess (optional, uses heuristic if None)
timeout (float) – Maximum total solve time in seconds (default: 200ms)
eomg (float) – Orientation tolerance in radians (default: 1e-4)
ev (float) – Position tolerance in meters (default: 1e-4)
num_restarts (int) – Number of initial guesses (default: 5)
use_parallel (bool) – Run DLS+SQP in parallel per guess (default: False)
- Returns:
Tuple of (theta, success, solve_time) - theta: Joint configuration (best found if not successful) - success: True if solution within tolerances - solve_time: Actual solve time in seconds
- Return type:
Example
>>> # Basic usage >>> theta, success, time = robot.trac_ik(T_target) >>> print(f"Solved: {success} in {time*1000:.1f}ms") >>> >>> # For real-time control (tight timeout) >>> theta, success, time = robot.trac_ik( ... T_target, ... theta0=current_angles, # Warm start ... timeout=0.01, # 10ms for 100Hz control ... num_restarts=2 ... )
Usage Examples
Basic Setup:
from ManipulaPy.kinematics import SerialManipulator
import numpy as np
# Define robot parameters
M = np.array([[1, 0, 0, 0.5],
[0, 1, 0, 0.0],
[0, 0, 1, 0.3],
[0, 0, 0, 1]])
omega_list = np.array([[0, 0, 1], # Joint 1: Z-axis rotation
[0, 1, 0], # Joint 2: Y-axis rotation
[0, 1, 0]]) # Joint 3: Y-axis rotation
robot = SerialManipulator(M_list=M, omega_list=omega_list)
Forward Kinematics:
# Compute end-effector pose
joint_angles = [0.5, -0.3, 0.8]
T = robot.forward_kinematics(joint_angles, frame="space")
print(f"Position: {T[:3, 3]}")
print(f"Orientation:\n{T[:3, :3]}")
# Get pose as [x, y, z, roll, pitch, yaw]
pose = robot.end_effector_pose(joint_angles)
Jacobian and Velocities:
# Compute Jacobian matrix
J = robot.jacobian(joint_angles, frame="space")
print(f"Jacobian shape: {J.shape}")
# Forward velocity kinematics
joint_velocities = [0.1, 0.2, -0.1]
ee_velocity = robot.end_effector_velocity(joint_angles, joint_velocities)
# Inverse velocity kinematics
desired_velocity = [0.05, 0.0, 0.1, 0.0, 0.0, 0.2]
required_joint_vel = robot.joint_velocity(joint_angles, desired_velocity)
Inverse Kinematics:
# Define target pose
T_target = np.array([[0, -1, 0, 0.3],
[1, 0, 0, 0.2],
[0, 0, 1, 0.4],
[0, 0, 0, 1]])
# Solve inverse kinematics
initial_guess = [0, 0, 0]
solution, success, iterations = robot.iterative_inverse_kinematics(
T_desired=T_target,
thetalist0=initial_guess,
eomg=1e-6,
ev=1e-6,
plot_residuals=True
)
if success:
print(f"IK converged in {iterations} iterations")
print(f"Solution: {solution}")
else:
print("IK failed to converge")
State Management:
# Update robot state
current_positions = [0.1, 0.2, 0.3]
current_velocities = [0.05, 0.1, 0.0]
robot.update_state(current_positions, current_velocities)
# Access current state
print(f"Current positions: {robot.joint_positions}")
print(f"Current velocities: {robot.joint_velocities}")
Joint Limits:
# Define joint limits
joint_limits = [(-np.pi, np.pi), # Joint 1: ±180°
(-np.pi/2, np.pi/2), # Joint 2: ±90°
(-np.pi/4, np.pi/4)] # Joint 3: ±45°
robot = SerialManipulator(
M_list=M,
omega_list=omega_list,
joint_limits=joint_limits
)
# Limits are enforced during IK solving
Key Features
Product of Exponentials formulation for robust kinematics
Dual frame support (space and body frames) for flexibility
Automatic screw axis computation from joint parameters
Damped least squares IK with singularity handling
Joint limit enforcement during inverse kinematics
Comprehensive velocity kinematics with pseudoinverse
Convergence visualization for debugging IK problems
Mathematical Background
Screw Theory Foundation:
Uses 6D twist vectors to represent joint motion
Exponential coordinates for robust orientation handling
Adjoint transformations for frame conversions
Jacobian Computation:
Space Jacobian: J_s = [Ad_{T₁} S₁, …, Ad_{Tᵢ} Sᵢ, …]
Body Jacobian: J_b computed via inverse transformations
Pseudoinverse used for redundant/singular configurations
Inverse Kinematics:
Newton-Raphson iteration in twist coordinates
Separate convergence criteria for translation and rotation
Adaptive step size for stability (α = 0.058)
See Also
Dynamics API Reference – Dynamics computations building on kinematics
Control API Reference – Controllers using kinematic models
Path Planning API Reference – Trajectory generation with kinematic constraints
Kinematics User Guide – Conceptual overview and theory what to replace here