Install & Compatibility
Where this runs
tested against v4.2.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
py 3.10
✕ build_error
✓ 13.73s
py 3.11
✕ build_error
✓ 13.03s
py 3.12
✕ build_error
✓ 12.7s
py 3.13
✕ build_error
✓ 12.9s
py 3.9
✕ build_error
1/4 runs
609MB installed
● package 609MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
solve_ik
✓ from pink import solve_ik
FrameTask
✓ from pink.tasks import FrameTask
✗ from pink.tasks import BodyTask
BodyTask was renamed to FrameTask in v2.0.0.
JointVelocityTask
✓ from pink.tasks import JointVelocityTask
RollingTask
✓ from pink.tasks import RollingTask
RelativeFrameTask
✓ from pink.tasks import RelativeFrameTask
PinkError
✓ from pink.exceptions import PinkError
✗ from pink import PinkError
Exceptions were moved to the `pink.exceptions` submodule in v3.3.0.
NoSolutionFound
✓ from pink.exceptions import NoSolutionFound
✗ raise AssertionError(...) for no solution
NoSolutionFound exception was introduced in v3.2.0, replacing AssertionErrors for non-convergent QP solutions.
FloatingBaseVelocityLimit
✓ from pink.limits import FloatingBaseVelocityLimit
JointLimit
✓ from pink.limits import JointLimit
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!")
Upgrade
Version history
4.2.0latest on PyPI · released Apr 20, 2026
Audit
Dependencies
pinocchiorequiredCore dependency for robot model representation and kinematics.
numpyrequiredNumerical operations, required by pinocchio and pink.