{"id":8419,"library":"pin-pink","title":"Inverse Kinematics for Articulated Robot Models (pink)","description":"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.","status":"active","version":"4.1.0","language":"python","source_language":"en","source_url":"https://github.com/stephane-caron/pink","tags":["robotics","inverse kinematics","control","pinocchio","manipulation","qp solver"],"install":[{"cmd":"pip install pin-pink","lang":"bash","label":"Install with pip"},{"cmd":"conda install -c conda-forge pin-pink","lang":"bash","label":"Install with conda (recommended for performance)"}],"dependencies":[{"reason":"Core dependency for robot model representation and kinematics.","package":"pinocchio","optional":false},{"reason":"Numerical operations, required by pinocchio and pink.","package":"numpy","optional":false}],"imports":[{"symbol":"solve_ik","correct":"from pink import solve_ik"},{"note":"BodyTask was renamed to FrameTask in v2.0.0.","wrong":"from pink.tasks import BodyTask","symbol":"FrameTask","correct":"from pink.tasks import FrameTask"},{"symbol":"JointVelocityTask","correct":"from pink.tasks import JointVelocityTask"},{"symbol":"RollingTask","correct":"from pink.tasks import RollingTask"},{"symbol":"RelativeFrameTask","correct":"from pink.tasks import RelativeFrameTask"},{"note":"Exceptions were moved to the `pink.exceptions` submodule in v3.3.0.","wrong":"from pink import PinkError","symbol":"PinkError","correct":"from pink.exceptions import PinkError"},{"note":"NoSolutionFound exception was introduced in v3.2.0, replacing AssertionErrors for non-convergent QP solutions.","wrong":"raise AssertionError(...) for no solution","symbol":"NoSolutionFound","correct":"from pink.exceptions import NoSolutionFound"},{"symbol":"FloatingBaseVelocityLimit","correct":"from pink.limits import FloatingBaseVelocityLimit"},{"symbol":"JointLimit","correct":"from pink.limits import JointLimit"}],"quickstart":{"code":"import numpy as np\nimport pinocchio as pin\nfrom pink import solve_ik\nfrom pink.tasks import FrameTask\n\n# 1. Load a sample robot model from Pinocchio\nmodel = pin.buildSampleModelManipulator()\nrobot = pin.RobotWrapper(model)\n\n# 2. Initial configuration (q0 is usually the home configuration)\nq = robot.q0\n\n# 3. Define tasks\n# Target an end-effector frame (e.g., the last frame in the model)\ntip_name = robot.model.frames[-1].name\ntip_id = robot.model.getFrameId(tip_name)\n\n# Get initial end-effector pose\nrobot.data = robot.model.createData()\npin.framesForwardKinematics(robot.model, robot.data, q)\ninitial_tip_pose = robot.data.oMf[tip_id].copy()\n\n# Define a target pose: move the tip 10cm upwards from its initial position\ntarget_pose = initial_tip_pose.copy()\ntarget_pose.translation += np.array([0.0, 0.0, 0.1])\n\n# Create a FrameTask to track the target pose\ntask = FrameTask(\n    tip_name,\n    lm_damping=1e-6 # Levenberg-Marquardt damping for stability\n)\ntask.set_target(target_pose)\n\ntasks = [task]\n\n# 4. Solve IK iteratively\ndt = 0.001  # Integration timestep\nnum_iterations = 500\nsolution_found = False\n\nprint(f\"Starting IK for {tip_name} to reach target position: {target_pose.translation}\")\n\nfor i in range(num_iterations):\n    try:\n        # Solve for joint velocities to achieve tasks\n        velocity = solve_ik(robot.model, robot.data, q, tasks, dt)\n    except Exception as e:\n        # print(f\"IK failed at iteration {i}: {e}\")\n        break\n\n    # Integrate joint velocities to update configuration\n    q = pin.integrate(robot.model, q, velocity * dt)\n\n    # Update forward kinematics for error calculation\n    pin.framesForwardKinematics(robot.model, robot.data, q)\n    current_tip_pose = robot.data.oMf[tip_id]\n\n    # Calculate position error\n    error = np.linalg.norm(current_tip_pose.translation - target_pose.translation)\n\n    if error < 1e-4: # Tolerance for reaching target\n        solution_found = True\n        # print(f\"Target reached in {i+1} iterations. Final error: {error:.6f}\")\n        break\n\nassert np.linalg.norm(current_tip_pose.translation - target_pose.translation) < 1e-3, \\\n    \"IK did not converge to target position within tolerance.\"\nprint(\"IK Quickstart Example: Success!\")","lang":"python","description":"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."},"warnings":[{"fix":"Update calls to `compute_qp_inequalities` to pass a `pin.Configuration` object. Review the new `Limits` API for details.","message":"The API for `Limit.compute_qp_inequalities` changed in v4.0.0. It now expects a full configuration instance as an argument, rather than just a configuration vector.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Replace `from pink.tasks import BodyTask` with `from pink.tasks import FrameTask` and update all instantiations of `BodyTask` to `FrameTask`.","message":"The `BodyTask` class was renamed to `FrameTask` in v2.0.0. Code using `BodyTask` will fail with an `AttributeError`.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Update exception imports to `from pink.exceptions import PinkError` (or other specific exceptions like `NoSolutionFound`).","message":"All custom exceptions were moved to the `pink.exceptions` submodule in v3.3.0. Direct imports like `from pink import PinkError` will no longer work.","severity":"gotcha","affected_versions":">=3.3.0"},{"fix":"Replace `except AssertionError` with `except NoSolutionFound` for cases where the IK solver fails to find a valid velocity. Consider checking `exn.results.x is not None` to distinguish between solver failure and non-convergence to a solution.","message":"The `NoSolutionFound` exception was introduced in v3.2.0, replacing previous `AssertionError` instances when the QP solver converged but did not find a solution. Code relying on catching `AssertionError` for this specific case will need updating.","severity":"gotcha","affected_versions":">=3.2.0"}],"env_vars":null,"search_vec":"'4.1.0':66 'activ':71 'allow':39 'articul':4,21 'base':36 'built':24 'control':53,82 'current':63 'cycl':73 'defin':42 'develop':72 'e.g':45 'effector':48 'end':47 'end-effector':46 'flexibl':33 'framework':29 'ik':19,37 'invers':1,17,80 'joint':50 'kinemat':2,18,81 'librari':15 'limit':51 'maintain':69 'manipul':84 'model':6,23 'object':44 'per':77 'pin':10 'pin-pink':9 'pink':7,8,11 'pinocchio':27,83 'program':60 'provid':31 'python':14 'qp':61,85 'quadrat':59 'releas':76 'resolv':56 'robot':5,22,28,79 'sever':75 'solver':38,86 'task':35 'task-bas':34 'track':49 'upon':25 'use':57 'user':40 'various':43 'veloc':52 'version':64 'year':78","created_at":"2026-04-16T17:02:05.808564+00:00","updated_at":"2026-04-16T17:02:05.808564+00:00","problems":{"verify_error":"/tmp/tmp6hd5pag7/venv/lib/python3.12/site-packages/qpsolvers/solvers/__init__.py:1087: UserWarning: no QP solver found on your system, you can install solvers from PyPI by ``pip install qpsolvers[open_source_solvers]``\n  warnings.warn(\nTraceback (most recent call last):\n  File \"<string>\", line 1, in"},"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"4.2.0","cli_name":"","cli_version":null,"type":"library","homepage":"https://stephane-caron.github.io/pink/","github":"https://github.com/stephane-caron/pink","docs":"https://stephane-caron.github.io/pink/","changelog":"https://github.com/stephane-caron/pink/blob/main/CHANGELOG.md","pypi":"https://pypi.org/project/pin-pink/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["ai-ml"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"install_fail","verified_at":"2026-06-28","last_verified":"2026-06-28","next_check":"2026-07-09","install_tag":null}}