This repository contains the implementation from “HJCD-IK: GPU-Accelerated Inverse Kinematics through Batched Hybrid Jacobian Coordinate Descent”.
HJCD-IK is a GPU-accelerated, sampling-based hybrid inverse kinematics solver for generating one or more robot configurations for a target end-effector pose.
- Linux
- NVIDIA GPU
- CUDA Toolkit 12.x or 13.x
- Python 3.9 or newer
- CMake 3.23 or newer
- GCC or Clang
- Eigen3
- nlohmann-json
Clone the repository:
git clone --recurse-submodules https://github.com/A2R-Lab/HJCD-IK.git
cd HJCD-IKRun the development setup:
chmod +x scripts/setup/setup_dev.sh
./scripts/setup/setup_dev.sh
source .venv/bin/activateThe script initializes the required submodules, creates a virtual environment,
installs dependencies, generates the robot model, and builds hjcdik.
If needed, convert the shell scripts to Unix line endings:
dos2unix scripts/setup/*.sh scripts/bench/*.shVerify the installation:
python - <<'PY'
import hjcdik
print("hjcdik:", hjcdik.__file__)
print("robot DoF:", hjcdik.num_joints())
PYInitialize the required submodules:
./scripts/setup/bootstrap.shCreate a virtual environment:
python3 -m venv .venv
source .venv/bin/activateInstall dependencies:
python -m pip install --upgrade \
pip \
setuptools \
wheel \
cmake \
ninja \
scikit-build-core
python -m pip install \
numpy \
scipy \
sympy \
beautifulsoup4 \
lxml \
pytestGenerate the Panda model:
python scripts/codegen/generate_grid.py \
csrc/urdf/panda.urdf \
-t panda_grasptarget_handBuild the package:
python -m pip install -e . --no-build-isolationimport hjcdik
target = hjcdik.sample_targets(num_targets=1, seed=0)[0]
result = hjcdik.generate_solutions(
target,
batch_size=2000,
num_solutions=1,
)
print("solutions:", result["count"])
print("joint configurations:", result["joint_config"])
print("position errors:", result["pos_errors"])
print("orientation errors:", result["ori_errors"])Target poses use:
[x, y, z, qw, qx, qy, qz]
Position is in meters and quaternions use wxyz order.
Generate the Panda collision model:
python scripts/codegen/generate_grid.py \
csrc/urdf/panda.urdf \
-t panda_grasptarget_hand \
--collision \
--spherized-urdf \
external/foam/assets/panda/smaller_panda_spherized.urdfRebuild:
python -m pip install -e . --no-build-isolationAfter any code-generation change, rebuild with:
bash scripts/setup/rebuild.shNote: the tests and collision-free example require a collision-enabled build.
Run the included examples:
python examples/01_open_world_solve.py
python examples/02_collision_free_solve.py
python examples/03_batch_sweep.pyFor the full test suite, use the collision-enabled Panda build above.
Run:
python -m pytest tests/ -vRun one test file:
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 \
python -m pytest tests/test_fk_equivalence.py -vRun the default HJCD benchmark:
python benchmark/hjcd_ik_bench.py \
--skip-grid-codegenThis runs 100 targets with batch sizes:
1, 10, 100, 1000, 2000
and writes results to:
results.yml
--num-targets <int>
--batches "<list>"
--num-solutions <int>
--yaml-out <path>
--urdf <path>
--grid-target <name>
--skip-grid-codegen
--seed <int>
Example:
python benchmark/hjcd_ik_bench.py \
--batches "1,32,256,2048" \
--num-targets 250 \
--num-solutions 4 \
--yaml-out results.yml \
--skip-grid-codegenRun the Panda MotionBenchMaker benchmark:
python benchmark/hjcd_ik_bench.py \
--skip-grid-codegen \
--collision-free \
--problems-json tests/mb_problems.json \
--problem-set box_panda \
--batches "1,10,100,1000,2000"Collision modes are selected with HJCD_CC_MODE:
HJCD_CC_MODE=soft python benchmark/hjcd_ik_bench.py ...
HJCD_CC_MODE=hard python benchmark/hjcd_ik_bench.py ...
HJCD_CC_MODE=both python benchmark/hjcd_ik_bench.py ...soft: biases solutions away from environment collisionshard: filters self- and environment-colliding solutionsboth: combines both modes
The paper benchmark can also run:
- PyRoki
- cuRobo v2
- IKFlow
- TRAC-IK
Install available baselines:
./scripts/setup/install_baselines.shSkip individual solvers when needed:
SKIP_CUROBO=1 ./scripts/setup/install_baselines.sh
SKIP_PYROKI=1 ./scripts/setup/install_baselines.sh
SKIP_IKFLOW=1 ./scripts/setup/install_baselines.sh
SKIP_TRACIK=1 ./scripts/setup/install_baselines.shNotes:
- cuRobo requires a compatible
cuda-corebackend. - IKFlow requires model weights under
benchmark/assets/ikflow/weights/. - TRAC-IK requires additional native dependencies.
See
docs/source/user_guide/benchmarks/results.rst
for detailed baseline instructions.
HJCD_REGEN=1 \
SKIP_PYROKI=1 \
SKIP_CUROBO=1 \
SKIP_IKFLOW=1 \
./scripts/bench/run_paper_experiments.shHJCD_REGEN=1 \
./scripts/bench/run_paper_experiments.shHJCD_REGEN=1 \
RUN_FETCH=1 \
RUN_DOF=1 \
RUN_MMD=1 \
./scripts/bench/run_paper_experiments.shResults are written to:
benchmark/results/
Use HJCD_REGEN=1 when running the paper benchmarks to ensure that HJCD-IK is rebuilt for the correct robot and end-effector frame.
After running the paper harness, restore the collision-enabled Panda build if you plan to run collision examples or tests:
python scripts/codegen/generate_grid.py \
csrc/urdf/panda.urdf \
-t panda_grasptarget_hand \
--collision \
--spherized-urdf \
external/foam/assets/panda/smaller_panda_spherized.urdf
python -m pip install -e . --no-build-isolationBenchmark timings depend on the GPU and system load. Run timing experiments on an otherwise idle GPU.
Generate a robot-specific model:
python scripts/codegen/generate_grid.py \
<PATH_TO_URDF> \
-t <FIXED_TARGET_NAME>Example:
python scripts/codegen/generate_grid.py \
csrc/urdf/fetch.urdf \
-t ee_fixedThen rebuild:
python -m pip install -e . --no-build-isolationHJCD-IK supports revolute, prismatic, and fixed joints.
Generate collision spheres from the URDF:
python scripts/codegen/generate_grid.py \
path/to/robot.urdf \
-t end_effector_fixed_joint \
--collision \
--collision-res 0.02Or use a pre-spherized foam URDF:
python scripts/codegen/generate_grid.py \
path/to/robot.urdf \
-t end_effector_fixed_joint \
--collision \
--spherized-urdf path/to/robot_spherized.urdfCollision environments use a MotionBenchMaker-style JSON format.
Each problem may contain:
goal_pose
start
world_frame
obstacles
Examples are available in:
tests/mb_problems.json
Supported obstacle types are:
spherecuboidcylinder
"cuboid": {
"box": {
"dims": [0.30, 0.25, 0.80],
"pose": [-0.05, 0.00, -0.40, 1, 0, 0, 0]
}
}"cylinder": {
"post": {
"radius": 0.035,
"height": 0.24,
"pose": [0.35, 0.15, 0.12, 1, 0, 0, 0]
}
}"sphere": {
"ball": {
"radius": 0.05,
"pose": [0.40, 0.10, 0.30, 1, 0, 0, 0]
}
}All poses use:
[x, y, z, qw, qx, qy, qz]
@inproceedings{yasutake2026hjcdik,
title = {{HJCD-IK}: {GPU}-Accelerated Inverse Kinematics through Batched Hybrid Jacobian Coordinate Descent},
author = {Yasutake, Cael and Liu, Andrew H. and Kingston, Zachary and Plancher, Brian},
booktitle = {2026 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS)},
year = {2026},
note = {arXiv:2510.07514}
}HJCD-IK is released under the MIT License.
This material is based upon work supported by the National Science Foundation (under Award 2411369). Any opinions, findings, conclusions, or recommendations expressed in this material are those of the authors and do not necessarily reflect those of the funding organizations.