Inverse Kinematics for Articulated Robot Models (pink)

4.1.0 · active · verified Thu Apr 16

Pink (pin-pink) is a Python library for inverse kinematics (IK) of articulated robot models, built upon the Pinocchio robotics framework. It provides a flexible task-based IK solver, allowing users to define various objectives (e.g., end-effector tracking, joint limits, velocity control) that are resolved using a quadratic program (QP). The current version is 4.1.0, and it maintains an active development cycle with several releases per year.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates how to use `pin-pink` to perform inverse kinematics for a simple manipulator robot. It loads a sample robot model, defines an end-effector tracking task to move it to a target position, and then iteratively solves for joint velocities to reach that target.

import numpy as np
import pinocchio as pin
from pink import solve_ik
from pink.tasks import FrameTask

# 1. Load a sample robot model from Pinocchio
model = pin.buildSampleModelManipulator()
robot = pin.RobotWrapper(model)

# 2. Initial configuration (q0 is usually the home configuration)
q = robot.q0

# 3. Define tasks
# Target an end-effector frame (e.g., the last frame in the model)
tip_name = robot.model.frames[-1].name
tip_id = robot.model.getFrameId(tip_name)

# Get initial end-effector pose
robot.data = robot.model.createData()
pin.framesForwardKinematics(robot.model, robot.data, q)
initial_tip_pose = robot.data.oMf[tip_id].copy()

# Define a target pose: move the tip 10cm upwards from its initial position
target_pose = initial_tip_pose.copy()
target_pose.translation += np.array([0.0, 0.0, 0.1])

# Create a FrameTask to track the target pose
task = FrameTask(
    tip_name,
    lm_damping=1e-6 # Levenberg-Marquardt damping for stability
)
task.set_target(target_pose)

tasks = [task]

# 4. Solve IK iteratively
dt = 0.001  # Integration timestep
num_iterations = 500
solution_found = False

print(f"Starting IK for {tip_name} to reach target position: {target_pose.translation}")

for i in range(num_iterations):
    try:
        # Solve for joint velocities to achieve tasks
        velocity = solve_ik(robot.model, robot.data, q, tasks, dt)
    except Exception as e:
        # print(f"IK failed at iteration {i}: {e}")
        break

    # Integrate joint velocities to update configuration
    q = pin.integrate(robot.model, q, velocity * dt)

    # Update forward kinematics for error calculation
    pin.framesForwardKinematics(robot.model, robot.data, q)
    current_tip_pose = robot.data.oMf[tip_id]

    # Calculate position error
    error = np.linalg.norm(current_tip_pose.translation - target_pose.translation)

    if error < 1e-4: # Tolerance for reaching target
        solution_found = True
        # print(f"Target reached in {i+1} iterations. Final error: {error:.6f}")
        break

assert np.linalg.norm(current_tip_pose.translation - target_pose.translation) < 1e-3, \
    "IK did not converge to target position within tolerance."
print("IK Quickstart Example: Success!")

view raw JSON →