How to Implement Inverse Kinematics in DART Using the IKFast Module
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:
-
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 atexamples/wam_ikfast/ikfast/ikfast71.Transform6D.4_6_9_10_11_12_f8.cpp. -
Shared-Library Wrapper: The
SharedLibraryIkFastclass (defined indart/dynamics/shared_library_ik_fast.hppand implemented indart/dynamics/shared_library_ik_fast.cpp) loads your compiled.so,.dylib, or.dllat runtime usingdart::common::SharedLibrary::create. It binds required symbols likeGetNumFreeParametersandComputeIkvia theloadFunctionhelper, then exposes these through virtual overrides such ascomputeIk()andgetNumJoints(). -
DART Analytical IK API: The abstract
IkFastbase class (indart/dynamics/ik_fast.hpp) integrates withdart::dynamics::InverseKinematics. When you callsetGradientMethod<SharedLibraryIkFast>(), theInverseKinematics::Analyticalsubsystem stores DOF mappings and forwards solution requests to the loaded solver’sComputeIkfunction.
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:
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 following the pattern in examples/wam_ikfast/ikfast/CMakeLists.txt:
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:
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 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:
#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:
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:
// 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
dartpyas a fallback
Summary
- Generate the IKFast solver using OpenRAVE’s
ikfast_generator_cpp.pyfor your specific robot URDF and IK type (e.g.,Transform6D). - Compile the generated C++ file into a shared library with
IKFAST_NO_MAINandIKFAST_CLIBRARYdefinitions. - Load the library in DART using
SharedLibraryIkFast, which bindsComputeIk,ComputeFk, and other required symbols at runtime viadart::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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →