# Implementing Inverse Kinematics (IK) for Robot Control in Newton: A Complete Guide

> Master robot control in Newton with our complete guide to implementing inverse kinematics IK. Leverage Newton's GPU-accelerated IK framework for efficient position and orientation problem solving.

- Repository: [Newton Physics/newton](https://github.com/newton-physics/newton)
- Tags: how-to-guide
- Published: 2026-03-19

---

**Newton provides a GPU-accelerated IK framework that solves position and orientation constraints for articulated robots using a single high-level API call.**

Implementing inverse kinematics for robot control in Newton leverages a modular, Warp-based pipeline that runs entirely on the GPU. The system, exposed through the [`newton/ik.py`](https://github.com/newton-physics/newton/blob/main/newton/ik.py) module, orchestrates objectives, optimizers, and samplers to solve thousands of parallel IK problems with minimal CPU overhead. This guide covers the architecture, implementation steps, and optimization strategies for production robot control.

## How Newton's IK System Works

Newton's IK architecture separates concerns into three distinct components that communicate through GPU buffers. The entry point is the `IKSolver` class in [`newton/ik.py`](https://github.com/newton-physics/newton/blob/main/newton/ik.py), which manages the optimization loop and seed selection.

### Core Components: Objectives, Optimizers, and Samplers

**Objectives** encode the geometric constraints that the solver must satisfy. The built-in implementations in [`newton/_src/sim/ik/ik_objectives.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/ik/ik_objectives.py) include:

- `IKObjectivePosition` – Targets a specific world position for a link
- `IKObjectiveRotation` – Targets a specific orientation using quaternions
- `IKObjectiveJointLimit` – Applies soft penalties when joints exceed bounds

**Optimizers** perform the numerical optimization on residuals and Jacobians. Defined in [`newton/_src/sim/ik/ik_solver.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/ik/ik_solver.py):

- `IKOptimizerLM` – Levenberg-Marquardt for robust nonlinear least squares
- `IKOptimizerLBFGS` – Limited-memory BFGS for large-scale problems with many degrees of freedom

**Samplers** generate initial seed configurations to improve convergence robustness. The `IKSampler` enum supports `NONE`, `GAUSS`, `UNIFORM`, and `ROBERTS` (low-discrepancy) strategies, implemented via kernels in [`ik_solver.py`](https://github.com/newton-physics/newton/blob/main/ik_solver.py).

## Setting Up Your First IK Solver in Newton

Implementing IK in Newton follows a four-step workflow: build the model, define objectives, configure the solver, and execute the solve step.

### Step 1: Build the Robot Model

Load your robot definition using `ModelBuilder` and finalize it before passing to the IK system:

```python
import newton as nd

builder = nd.ModelBuilder()
builder.add_mjcf(nd.utils.download_asset("franka_panda") / "mjcf/panda_with_hand.xml")
builder.add_ground_plane()
model = builder.finalize()

```

### Step 2: Define IK Objectives

Create objective instances for each constraint. For a simple reach task:

```python
import warp as wp
import newton.ik as ik

target = wp.array([wp.vec3(0.4, 0.0, 0.2)], dtype=wp.vec3)
pos_obj = ik.IKObjectivePosition(
    link_index=7,
    link_offset=wp.vec3(0, 0, 0),
    target_positions=target,
    weight=1.0,
)

```

### Step 3: Configure the IKSolver

Instantiate the solver with your model, objectives, and optimization parameters:

```python
solver = ik.IKSolver(
    model=model,
    n_problems=1,
    objectives=[pos_obj],
    optimizer=ik.IKOptimizer.LM,
    jacobian_mode=ik.IKJacobianType.ANALYTIC,
    sampler=ik.IKSampler.GAUSS,
    n_seeds=8,
    noise_std=0.05,
)

```

### Step 4: Execute the Solve Step

Call `step()` each frame with input and output buffers. The solver writes solved configurations to `joint_q_out`:

```python
q_in = model.joint_q.reshape((1, -1))
q_out = wp.zeros_like(q_in)

solver.step(q_in, q_out, iterations=24)

# q_out now contains the solved joint angles

```

## Complete Code Examples for Newton IK

The following examples demonstrate production-ready implementations for common robot control scenarios.

### Minimal Point-to-Point IK

This snippet solves a single position target for a Franka Emika Panda arm using LBFGS optimization:

```python
import warp as wp
import newton as nd
import newton.ik as ik

# Build model

builder = nd.ModelBuilder()
builder.add_mjcf(nd.utils.download_asset("franka_panda") / "mjcf/panda_with_hand.xml")
model = builder.finalize()

# Define position objective for end-effector (link 7)

target_pos = wp.array([wp.vec3(0.4, 0.0, 0.2)], dtype=wp.vec3)
pos_obj = ik.IKObjectivePosition(
    link_index=7,
    link_offset=wp.vec3(0, 0, 0),
    target_positions=target_pos,
    weight=1.0,
)

# Configure solver with LBFGS

solver = ik.IKSolver(
    model=model,
    n_problems=1,
    objectives=[pos_obj],
    optimizer=ik.IKOptimizer.LBFGS,
    jacobian_mode=ik.IKJacobianType.ANALYTIC,
)

# Solve

q = model.joint_q.reshape((1, -1))
solver.step(q, q, iterations=10)
print("Solved joint angles:", q.numpy())

```

### Position, Rotation, and Joint Limits

This example combines multiple constraint types for precise end-effector control while respecting mechanical limits:

```python

# Assume model is built as above

# ...

# Position objective

pos_obj = ik.IKObjectivePosition(
    link_index=7,
    link_offset=wp.vec3(0, 0, 0),
    target_positions=wp.array([wp.vec3(0.5, 0.1, 0.3)], dtype=wp.vec3),
    weight=1.0,
)

# Rotation objective (target identity quaternion)

target_rot = wp.array([wp.vec4(0, 0, 0, 1)], dtype=wp.vec4)
rot_obj = ik.IKObjectiveRotation(
    link_index=7,
    link_offset_rotation=wp.quat_identity(),
    target_rotations=target_rot,
    weight=0.5,
)

# Joint limit objective (soft penalty)

limit_obj = ik.IKObjectiveJointLimit(
    joint_limit_lower=model.joint_limit_lower,
    joint_limit_upper=model.joint_limit_upper,
    weight=10.0,
)

# Assemble solver with Levenberg-Marquardt and Gaussian sampling

solver = ik.IKSolver(
    model=model,
    n_problems=1,
    objectives=[pos_obj, rot_obj, limit_obj],
    optimizer=ik.IKOptimizer.LM,
    jacobian_mode=ik.IKJacobianType.ANALYTIC,
    sampler=ik.IKSampler.GAUSS,
    n_seeds=8,
    noise_std=0.03,
)

# Solve

q = model.joint_q.reshape((1, -1))
solver.step(q, q, iterations=30)

```

### Batch Solving Multiple Robots

Solve 100 identical robot instances with different target positions in parallel:

```python
import numpy as np
import warp as wp
import newton as nd
import newton.ik as ik

# Build model

builder = nd.ModelBuilder()
builder.add_mjcf(nd.utils.download_asset("franka_panda") / "mjcf/panda_with_hand.xml")
model = builder.finalize()

# Batch configuration

n_problems = 100
q = wp.zeros((n_problems, model.joint_coord_count), dtype=wp.float32, device=model.device)

# Generate random targets

rng = np.random.default_rng(42)
targets_np = rng.uniform(-0.5, 0.5, size=(n_problems, 3)).astype(np.float32)
targets_wp = wp.array(targets_np, dtype=wp.vec3, device=model.device)

# Single objective applied to all problems

pos_obj = ik.IKObjectivePosition(
    link_index=7,
    link_offset=wp.vec3(0, 0, 0),
    target_positions=targets_wp,
    weight=1.0,
)

# Batch solver with uniform sampling

solver = ik.IKSolver(
    model=model,
    n_problems=n_problems,
    objectives=[pos_obj],
    optimizer=ik.IKOptimizer.LM,
    jacobian_mode=ik.IKJacobianType.ANALYTIC,
    sampler=ik.IKSampler.UNIFORM,
    n_seeds=4,
)

# Solve all 100 problems in parallel

solver.step(q, q, iterations=20)
print("Batch solved joint angles shape:", q.shape)

```

## Advanced Configuration and Performance Tuning

Optimizing IK performance in Newton requires selecting the right Jacobian mode, optimizer, and sampling strategy for your specific robot morphology.

### Choosing Between Analytic and Autodiff Jacobians

Newton supports two Jacobian computation modes via the `IKJacobianType` enum:

- **ANALYTIC** – Uses hand-derived Jacobians for position and rotation objectives. This mode is orders of magnitude faster on the GPU and should be preferred when available.
- **AUTODIFF** – Uses Warp's automatic differentiation tape to compute Jacobians. Use this for custom objectives where analytic derivatives are not implemented, or for complex constraint chains.

Set the mode when constructing the solver:

```python
solver = ik.IKSolver(
    model=model,
    n_problems=1,
    objectives=[pos_obj],
    jacobian_mode=ik.IKJacobianType.ANALYTIC,  # or .AUTODIFF

)

```

### Optimizer Selection: Levenberg-Marquardt vs LBFGS

Newton provides two optimization algorithms via the `IKOptimizer` enum:

- **LM (Levenberg-Marquardt)** – Robust nonlinear least squares solver ideal for standard IK problems with position and rotation objectives. Handles singularities well through damping.
- **LBFGS** – Quasi-Newton method better suited for highly redundant robots with many degrees of freedom where the Hessian approximation reduces iteration count.

For most robotic arms, `LM` provides the best balance of robustness and speed. For humanoid robots with 50+ joints, `LBFGS` often converges faster.

### Sampling Strategies for Robustness

When `n_seeds > 1`, Newton generates multiple initial configurations to avoid local minima:

- **GAUSS** – Adds Gaussian noise to the current configuration, clamping to joint limits. Best for fine-tuning near valid solutions.
- **UNIFORM** – Samples each joint uniformly within its limits. Better for global exploration when the target is far from the current pose.
- **ROBERTS** – Deterministic low-discrepancy sequence for reproducible coverage across batches.

Limit `n_seeds` to small powers of two (4–16) to minimize GPU memory traffic while maintaining robustness.

## Summary

- Newton's IK system lives in [`newton/ik.py`](https://github.com/newton-physics/newton/blob/main/newton/ik.py) and provides a GPU-accelerated pipeline for solving robot inverse kinematics.
- The architecture separates **Objectives** (constraints), **Optimizers** (LM and LBFGS), and **Samplers** (seed generation) for modular configuration.
- Use `IKJacobianType.ANALYTIC` for maximum performance on standard position/rotation tasks, and `AUTODIFF` for custom constraints.
- Batch solving supports `n_problems > 1` for parallel IK computation across hundreds of robot instances.
- Reference implementation available in [`newton/examples/ik/example_ik_h1.py`](https://github.com/newton-physics/newton/blob/main/newton/examples/ik/example_ik_h1.py) for interactive control of humanoid robots.

## Frequently Asked Questions

### What is the difference between analytic and autodiff Jacobians in Newton IK?

**Analytic Jacobians** are hand-derived mathematical gradients implemented in kernels like `_pos_jac_analytic` in [`newton/_src/sim/ik/ik_objectives.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/ik/ik_objectives.py). They execute directly on the GPU without recording operations to a tape, making them orders of magnitude faster for standard objectives. **Autodiff Jacobians** use Warp's automatic differentiation system to record the forward pass and compute gradients during backward propagation. Use autodiff when implementing custom objectives where manual Jacobian derivation is impractical.

### How do I handle joint limits when implementing IK in Newton?

Newton provides the `IKObjectiveJointLimit` class in [`newton/_src/sim/ik/ik_objectives.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/ik/ik_objectives.py) to enforce joint limits via soft penalties. Instantiate it with the model's `joint_limit_lower` and `joint_limit_upper` arrays, then include it in the solver's objectives list with an appropriate weight (typically 5.0–10.0). The objective adds a residual that pushes joints back into bounds when they exceed limits, and it supports analytic Jacobians for minimal performance overhead.

### Can Newton solve IK for multiple robots simultaneously?

Yes. Set `n_problems` to the desired batch size when constructing `IKSolver` in [`newton/ik.py`](https://github.com/newton-physics/newton/blob/main/newton/ik.py). The solver automatically reshapes all internal buffers to handle `(n_problems, n_coords)` arrays. Objectives like `IKObjectivePosition` accept target arrays where the first dimension matches `n_problems`, allowing you to specify different targets for each robot instance. This batching executes entirely on the GPU via Warp kernels, enabling parallel solving for hundreds of robots with a single API call.

### Where can I find the complete source code for Newton's IK system?

The public API resides in [[`newton/ik.py`](https://github.com/newton-physics/newton/blob/main/newton/ik.py)](https://github.com/newton-physics/newton/blob/main/newton/ik.py), which exports `IKSolver`, objective classes, and configuration enums. The core implementation lives in [[`newton/_src/sim/ik/ik_solver.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/ik/ik_solver.py)](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/ik/ik_solver.py) for optimization logic and [[`newton/_src/sim/ik/ik_objectives.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/ik/ik_objectives.py)](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/ik/ik_objectives.py) for constraint residuals and Jacobians. For a complete working example, see [[`newton/examples/ik/example_ik_h1.py`](https://github.com/newton-physics/newton/blob/main/newton/examples/ik/example_ik_h1.py)](https://github.com/newton-physics/newton/blob/main/newton/examples/ik/example_ik_h1.py), which demonstrates interactive IK control of a Unitree H1 humanoid robot.