mink - MuJoCo Inverse Kinematics
mink is a Python library for inverse kinematics (IK) based on MuJoCo, designed for robotics applications. It provides a flexible framework for defining kinematic tasks, joint limits, and collision avoidance, then solving for joint configurations. Currently at version 1.1.0, mink maintains an active development pace with recent releases focusing on performance improvements and stability.
Common errors
-
ModuleNotFoundError: No module named 'mujoco'
cause The `mujoco` Python package or its native libraries are not installed or configured correctly.fixRun `pip install mujoco` and ensure your system's MuJoCo native libraries are set up according to the official MuJoCo documentation (e.g., environment variables like `LD_LIBRARY_PATH` on Linux). -
RuntimeError: Python 3.8 is no longer supported by mink.
cause You are attempting to use `mink` version 1.0.0 or newer with an unsupported Python 3.8 environment.fixUpgrade your Python environment to version 3.9 or higher. For example, use `conda create -n myenv python=3.9` or similar. -
mink.exceptions.NoSolutionFound: No solution found for the given tasks.
cause The inverse kinematics solver could not find a valid set of joint angles to satisfy all target tasks, often due to an unreachable target, conflicting constraints, or joint limits.fixReview your target position/orientation, task weights, and robot's joint limits. Ensure the target is within the robot's reachable workspace. Consider adjusting weights or adding other tasks like `JointLimitTask` or `CollisionAvoidanceTask`. -
AttributeError: module 'mink' has no attribute 'KinematicTask'
cause You are trying to import a class or function from `mink` using an incorrect path or the symbol might have been renamed/moved in an older version.fixEnsure you are using the correct import statement as shown in the quickstart: `from mink import Configuration, KinematicTask, solve_ik`. Most commonly used classes are exposed directly in the top-level `mink` package.
Warnings
- breaking mink v1.0.0 dropped support for Python 3.8.
- gotcha mink relies on MuJoCo, which requires both the Python `mujoco` package and the native MuJoCo library to be installed and properly configured.
- gotcha The license of mink changed from GPL to MIT due to a dependency switch from `quadprog` to `DAQP`.
- gotcha The `solve_ik` function can now raise a `mink.exceptions.NoSolutionFound` error if the QP solver fails to find a solution.
- gotcha Issues with `Configuration.get_inertia_matrix()` were fixed for MuJoCo versions 3.3.4 and above.
Install
-
pip install mink
Imports
- Configuration
from mink import Configuration
- KinematicTask
from mink import KinematicTask
- JointLimitTask
from mink import JointLimitTask
- solve_ik
from mink import solve_ik
- build_ik
from mink import build_ik
Quickstart
import mujoco
from mink import Configuration, KinematicTask, solve_ik
import numpy as np
# Create a very simple MuJoCo model for demonstration
model_xml = """
<mujoco>
<worldbody>
<body name="link0" pos="0 0 0.1">
<joint name="joint0" type="hinge" axis="0 0 1" pos="0 0 0" />
<geom type="capsule" size="0.05 0.1" fromto="0 0 0 0 0 0.1" />
<body name="link1" pos="0 0 0.1">
<joint name="joint1" type="hinge" axis="0 1 0" pos="0 0 0" />
<geom type="capsule" size="0.05 0.1" fromto="0 0 0 0 0 0.1" />
<body name="tip" pos="0 0 0.1">
<geom type="sphere" size="0.02" rgba="1 0 0 1"/>
</body>
</body>
</body>
</worldbody>
</mujoco>
"""
model = mujoco.MjModel.from_xml_string(model_xml)
data = mujoco.MjData(model)
# Instantiate the configuration wrapper
config = Configuration(model, data)
# Define a kinematic task to reach a target position for the 'tip' body
target_position = np.array([0.0, 0.1, 0.3]) # Target in world coordinates
tasks = [
KinematicTask(
config=config,
body="tip", # Target the 'tip' body defined in the XML
target_pos=target_position,
weight=1.0,
)
]
# Solve Inverse Kinematics
q_sol, sol = solve_ik(tasks, config)
print(f"IK Solution (joint angles): {q_sol}")
# Update MuJoCo data with the solution to get the final tip position
config.set_joint_positions(q_sol)
mujoco.mj_fwdKin(model, data)
print(f"Final end-effector position: {config.get_body_position('tip')}")