Inverse Kinematics
SUMMARY
Inverse Kinematics computes joint configurations that achieve a requested end-effector pose.
This skill enables task-space targeting, robot pose solving, and execution planning for manipulation and industrial automation workflows.
The Skill
# target_pose can be a pose object from forward_kinematics, or a list [x, y, z, rx, ry, rz]
q = robot.inverse_kinematics(
target_pose=target_pose,
rot_type="rad",
q_init=q_init,
solver="clik",
)The Code
Example 1: IK from a pose object with a seeded initialization
Compute the target pose via FK, add noise to the known configuration to create a realistic seed, then solve IK.
import numpy as np
from loguru import logger
from telekinesis.synapse.robots.manipulators import kuka
robot = kuka.KukaKR6R9002()
q = np.asarray([0, -np.pi / 2 - 0.1, -np.pi / 2, 0, np.pi / 2, 0])
target_pose = robot.forward_kinematics(q, rot_type="rad")
noise = np.random.normal(loc=0.0, scale=0.5, size=q.shape)
q_init = q + noise
q = robot.inverse_kinematics(
target_pose=target_pose,
rot_type="rad",
q_init=q_init,
solver="clik",
)
logger.success(f"IK solution: {q}")Example 2: IK from a Cartesian list with a zero seed
Pass the target pose directly as [x, y, z, rx, ry, rz] and use a zero vector as the seed.
import numpy as np
from loguru import logger
from telekinesis.synapse.robots.manipulators import kuka
robot = kuka.KukaKR6R9002()
target_pose = [0.5, 0.2, 0.3, 3.14, 0.0, 0.0]
q_seed = np.zeros(6)
q = robot.inverse_kinematics(
target_pose=target_pose,
rot_type="rad",
q_init=q_seed,
solver="clik",
)
logger.success(f"IK solution: {q}")Example 3: Multi-start IK without a seed
Use solver="multi_start_clik" with q_init=None to search from multiple random seeds automatically. More robust when the starting configuration is unknown.
import numpy as np
from loguru import logger
from telekinesis.synapse.robots.manipulators import kuka
robot = kuka.KukaKR6R9002()
target_pose = [0.5, 0.2, 0.3, 3.14, 0.0, 0.0]
q = robot.inverse_kinematics(
target_pose=target_pose,
rot_type="rad",
q_init=None,
solver="multi_start_clik",
)
logger.success(f"IK solution: {q}")Example 4: Collision-free IK on a 7-DOF robot
For redundant robots such as the Kuka IIWA (7-DOF), pass collision_free_ik=True to filter solutions that collide with the environment.
import numpy as np
from loguru import logger
from telekinesis.synapse.robots.manipulators import kuka
robot = kuka.KukaLBRIIWA14R820()
target_pose = [0.5, 0.2, 0.3, 3.14, 0.0, 0.0]
q_seed = np.zeros(7)
q = robot.inverse_kinematics(
target_pose=target_pose,
rot_type="rad",
q_init=q_seed,
collision_free_ik=True,
)
logger.success(f"Collision-free IK solution: {q}")The Explanation of the Code
inverse_kinematics solves for joint configurations q that place the end-effector at target_pose. The solver is iterative — it starts from q_init and converges toward a solution. The quality and existence of the solution depends on the solver chosen and how close q_init is to a valid solution.
Target pose formats. target_pose accepts either a pose object returned by forward_kinematics, or a plain list [x, y, z, rx, ry, rz] where position is in metres and rotation is expressed as an axis-angle vector in the unit given by rot_type.
Solver choice. "clik" (Closed-Loop Inverse Kinematics) is a single-start gradient-based solver — fast but sensitive to q_init. "multi_start_clik" runs "clik" from several random seeds and returns the best result — slower but more robust when no good seed is available.
Seed (q_init). When q_init is None, the solver initialises from a default or random configuration. Providing a seed close to the expected solution significantly improves convergence speed and reliability.
Redundant robots. For robots with more than 6 DOF (e.g. IIWA with 7 joints), there is a continuous family of solutions. collision_free_ik=True filters this set to configurations that do not collide with the environment model.
How to Tune the Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
target_pose | pose object or list[float] | — | Target end-effector pose. List format: [x, y, z, rx, ry, rz]. Position in metres; rotation as axis-angle in rot_type units. |
rot_type | str | "rad" | Unit for joint angles in the returned solution and for interpreting rotation in target_pose. "rad" or "deg". |
q_init | np.ndarray or None | None | Initial joint configuration seed. Length must equal robot DOF. Set to None to use solver default. |
solver | str | "clik" | IK solver algorithm. "clik": single-start CLIK. "multi_start_clik": multi-start CLIK, more robust but slower. |
collision_free_ik | bool | False | Filter solutions to only those free of self-collision and environment collision. Primarily useful for redundant robots (7+ DOF). |
Choosing a solver
Use "clik" when you have a reliable seed (e.g. the previous joint state). Use "multi_start_clik" when the seed is unavailable or the pose is far from the robot's neutral configuration.
WARNING
Poses near kinematic singularities or outside the reachable workspace will raise a RuntimeError. Wrap calls in a try/except block in production code.
Where to Use the Skill
- Task-space motion planning — Convert a Cartesian target (from a grasp planner or vision pipeline) into joint commands
- Pick-and-place — Compute joint configurations for approach, grasp, and release poses defined in Cartesian space
- Trajectory generation — Solve IK at waypoints along a Cartesian path to build a joint-space trajectory
- Reachability checks — Verify offline whether a set of task poses are kinematically feasible before deployment
When Not to Use the Skill
Do not use Inverse Kinematics when:
- You already have a joint configuration and need the Cartesian pose — use Forward Kinematics instead
- The target pose is near a kinematic singularity — IK solutions become unstable; apply replanning or singularity avoidance upstream
- Low-latency real-time joint commands are required — pre-compute IK solutions offline and look them up at runtime instead

