# How to Implement Inverse Kinematics in DART Using the IKFast Module

> Implement inverse kinematics in DART using IKFast. Generate a C++ solver from your URDF, compile it, and load it with SharedLibraryIkFast for efficient motion planning.

- Repository: [DART: Dynamic Animation and Robotics Toolkit/dart](https://github.com/dartsim/dart)
- Tags: how-to-guide
- Published: 2026-02-28

---

**To implement inverse kinematics in DART using IKFast, you must generate a C++ solver from your robot URDF, compile it into a shared library, then load it at runtime using the `SharedLibraryIkFast` wrapper class and attach it to a `dart::dynamics::InverseKinematics` object via `setGradientMethod`.**

The DART simulation library (dartsim/dart) provides a built-in **analytical IK interface** that integrates with pre-generated IKFast solvers from OpenRAVE. This architecture allows you to swap the default gradient-based IK with a fast, closed-form solution for compatible robot kinematic chains.

## Understanding the IKFast Architecture in DART

DART’s IKFast integration follows a three-layer architecture that separates code generation from runtime execution:

1. **IKFast Generator** (external tool): Produces a single C++ file containing `ComputeIk`, `ComputeFk`, and related functions. The WAM arm example in the repository shows this output at [`examples/wam_ikfast/ikfast/ikfast71.Transform6D.4_6_9_10_11_12_f8.cpp`](https://github.com/dartsim/dart/blob/main/examples/wam_ikfast/ikfast/ikfast71.Transform6D.4_6_9_10_11_12_f8.cpp).

2. **Shared-Library Wrapper**: The `SharedLibraryIkFast` class (defined in [`dart/dynamics/shared_library_ik_fast.hpp`](https://github.com/dartsim/dart/blob/main/dart/dynamics/shared_library_ik_fast.hpp) and implemented in [`dart/dynamics/shared_library_ik_fast.cpp`](https://github.com/dartsim/dart/blob/main/dart/dynamics/shared_library_ik_fast.cpp)) loads your compiled `.so`, `.dylib`, or `.dll` at runtime using `dart::common::SharedLibrary::create`. It binds required symbols like `GetNumFreeParameters` and `ComputeIk` via the `loadFunction` helper, then exposes these through virtual overrides such as `computeIk()` and `getNumJoints()`.

3. **DART Analytical IK API**: The abstract `IkFast` base class (in [`dart/dynamics/ik_fast.hpp`](https://github.com/dartsim/dart/blob/main/dart/dynamics/ik_fast.hpp)) integrates with `dart::dynamics::InverseKinematics`. When you call `setGradientMethod<SharedLibraryIkFast>()`, the `InverseKinematics::Analytical` subsystem stores DOF mappings and forwards solution requests to the loaded solver’s `ComputeIk` function.

## Prerequisites: Generating and Compiling the IKFast Solver

Before running IK in DART, you must generate and compile the solver outside the DART codebase.

### Step 1: Generate the IKFast C++ Source

Use OpenRAVE’s generator script to create an analytical solver for your specific robot kinematics:

```bash
git clone https://github.com/rdiankov/openrave
cd openrave
python3 python/ikfast_generator_cpp.py \
    --robot=my_robot.urdf \
    --iktype=Transform6D \
    --freeindex=2 \
    --output=ikfast71.Transform6D.my_robot.cpp

```

This produces a file containing the `ComputeIk` function that calculates joint angles given a target end-effector transform.

### Step 2: Build the Shared Library

Create a minimal [`CMakeLists.txt`](https://github.com/dartsim/dart/blob/main/CMakeLists.txt) following the pattern in [`examples/wam_ikfast/ikfast/CMakeLists.txt`](https://github.com/dartsim/dart/blob/main/examples/wam_ikfast/ikfast/CMakeLists.txt):

```cmake
cmake_minimum_required(VERSION 3.12)
project(GeneratedMyRobotIkFast LANGUAGES CXX)

add_library(GeneratedMyRobotIkFast SHARED ikfast71.Transform6D.my_robot.cpp)
target_compile_definitions(GeneratedMyRobotIkFast PRIVATE IKFAST_NO_MAIN IKFAST_CLIBRARY)

```

Compile the library:

```bash
mkdir build && cd build
cmake .. && make

```

This produces `libGeneratedMyRobotIkFast.so` (Linux), `.dylib` (macOS), or `.dll` (Windows).

## Loading and Configuring the Solver in DART

With the shared library compiled, you can load it into a DART application. The integration test in [`tests/integration/io/test_ik_fast.cpp`](https://github.com/dartsim/dart/blob/main/tests/integration/io/test_ik_fast.cpp) demonstrates the complete workflow.

### Setting Up the Skeleton and End Effector

First, load your robot and create an IK object attached to the end-effector body node:

```cpp
#include <dart/dart.hpp>
using namespace dart::dynamics;

// Load robot model
auto skel = dart::io::readSkeleton(
    dart::common::Uri::createFromPath("path/to/robot.urdf"));
assert(skel);

// Create end-effector and IK controller
auto ee = skel->getBodyNode("hand")->createEndEffector("ee");
auto ik = ee->createIK();

```

### Configuring the Shared Library Wrapper

Use `setGradientMethod<SharedLibraryIkFast>()` to replace the default gradient-based solver with your analytical library. You must explicitly map the joint indices that IKFast solves versus those left as free parameters:

```cpp
std::string libPath = "libGeneratedMyRobotIkFast.so";  // Adjust extension per OS

// Indices must match the DOF order expected by your generated solver
std::vector<std::size_t> solvedDofs = {0, 1, 3, 4, 5, 6};
std::vector<std::size_t> freeDofs   = {2};

ik->setGradientMethod<SharedLibraryIkFast>(libPath, solvedDofs, freeDofs);

```

The `solvedDofs` vector lists the joint indices that the IKFast solver computes, while `freeDofs` contains indices passed as parameters during generation (e.g., the shoulder roll in a 7-DOF arm).

### Querying and Applying Solutions

Set a target transform and retrieve all valid configurations:

```cpp
// Configure target
auto target = dart::dynamics::SimpleFrame::createShared(
    dart::dynamics::Frame::World());
target->setTranslation(Eigen::Vector3d(0.3, 0.0, 0.5));
target->setRotation(Eigen::Matrix3d::Identity());
ik->setTarget(target);
ik->setHierarchyLevel(1);  // Optional: limits search depth

// Retrieve analytical solutions
auto analytical = ik->getAnalytical();  // Returns SharedLibraryIkFast*
auto solutions = analytical->getSolutions(ee->getTransform());

// Apply first valid solution
for (const auto& sol : solutions)
{
  if (sol.mValidity != dart::dynamics::InverseKinematics::Analytical::VALID) 
    continue;
  
  skel->setPositions(solvedDofs, sol.mConfig);
  break;
}

```

The `getSolutions()` method returns a `std::vector` of `InverseKinematics::Solution` objects, where `sol.mConfig` contains the joint values and `sol.mValidity` indicates if the configuration respects joint limits and collision constraints.

## Python Bindings Limitations

The `dartpy` Python bindings do **not** currently expose the `SharedLibraryIkFast` class directly, as noted in the documentation at `docs/readthedocs/shared/inverse_kinematics/ikfast.rst`. To use IKFast from Python, you must either:

- Write a thin C++ helper that calls the C++ API and expose it via `pybind11`
- Use DART’s gradient-based IK methods available in `dartpy` as a fallback

## Summary

- **Generate** the IKFast solver using OpenRAVE’s [`ikfast_generator_cpp.py`](https://github.com/dartsim/dart/blob/main/ikfast_generator_cpp.py) for your specific robot URDF and IK type (e.g., `Transform6D`).
- **Compile** the generated C++ file into a shared library with `IKFAST_NO_MAIN` and `IKFAST_CLIBRARY` definitions.
- **Load** the library in DART using `SharedLibraryIkFast`, which binds `ComputeIk`, `ComputeFk`, and other required symbols at runtime via `dart::common::SharedLibrary`.
- **Configure** the IK object by calling `setGradientMethod<SharedLibraryIkFast>()` with the library path and explicit DOF mappings for solved and free joints.
- **Solve** by calling `InverseKinematics::Analytical::getSolutions()` to retrieve all valid joint configurations for a target end-effector pose.

## Frequently Asked Questions

### What is the difference between gradient-based and analytical IK in DART?

**Gradient-based IK** (the default) uses Jacobian iteration to iteratively approach a solution, which is general-purpose but slower and may converge to local minima. **Analytical IK** via IKFast uses pre-generated closed-form equations that compute all valid solutions instantly, but requires a compatible kinematic structure and pre-processing step to generate the solver code.

### How do I map joint indices correctly when using SharedLibraryIkFast?

The `solvedDofs` vector must list the indices (in the DART skeleton) of joints that your IKFast solver was generated to compute, in the exact order the solver expects. The `freeDofs` vector lists indices of joints treated as free parameters during generation (often the first joint in a 7-DOF arm). Mismatches between these mappings and the generated solver will cause incorrect joint angle calculations or segmentation faults.

### Can I use IKFast with any robot arm in DART?

No, IKFast only works with kinematic chains that have a solvable analytical solution (typically 6 or 7 DOF arms with specific geometric configurations). You must first verify that OpenRAVE’s IKFast generator can produce a solver for your specific URDF. If generation fails, the robot likely requires numerical IK methods instead.

### Where can I find a complete working example?

The file [`tests/integration/io/test_ik_fast.cpp`](https://github.com/dartsim/dart/blob/main/tests/integration/io/test_ik_fast.cpp) contains a full integration test that loads a generated WAM arm solver, configures DOF maps, queries solutions for a target transform, and verifies that the end-effector pose matches the target within tolerance. Additionally, `examples/wam_ikfast/` shows the CMake configuration for compiling the generated solver.