Examples & Results ================== Runnable examples for the Python API, then the published benchmark results and how to reproduce them. Examples -------- Self-contained, runnable programs live in the repository's ``examples/`` directory. Each is included in full below (so the docs never drift from the code). Run any with the project's virtual environment active, e.g. ``python examples/01_open_world_solve.py``. .. list-table:: :header-rows: 1 :widths: 28 52 20 * - Example - Shows - Needs * - ``01_open_world_solve`` - Batch-solve one 6-DOF target; inspect the best returned solutions - built ``hjcdik`` * - ``02_collision_free_solve`` - Collision-free solve against a MotionBenchMaker scene (obstacles on GPU) - ``grasptarget`` build * - ``03_batch_sweep`` - How the best-solution accuracy improves with batch size - built ``hjcdik`` 01 — Open-world solve ~~~~~~~~~~~~~~~~~~~~~~~ .. literalinclude:: ../../../../examples/01_open_world_solve.py :language: python 02 — Collision-free solve ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The scene and goal come from ``tests/mb_problems.json``; the GPU filters candidates against the obstacles in the chosen problem set (the **Results** section below covers the benchmark harness and reproduction). .. literalinclude:: ../../../../examples/02_collision_free_solve.py :language: python 03 — Batch-size sweep ~~~~~~~~~~~~~~~~~~~~~~~ .. literalinclude:: ../../../../examples/03_batch_sweep.py :language: python Results ------- HJCD-IK generates large batches of IK solutions in parallel and stays on or near the **accuracy–latency Pareto frontier** across every batch size and degree-of-freedom count, with order-of-magnitude gains over the GPU baselines cuRobo, PyRoki, and IKFlow, while returning the most diverse (lowest-MMD) solution set. .. note:: **All numbers below are from the camera-ready paper** (`arXiv:2510.07514 `_, IROS 2026) — the single source of truth. They were collected on an NVIDIA RTX 4060 (Intel i7-14700HX, WSL Ubuntu 24.04, CUDA 12.5) over 100 Halton open-world poses and the *box_panda* MotionBenchMaker scene. Benchmarks you run locally (see *Reproducing these results*, below) are for your own validation and will differ with hardware. Position error is in **mm**, orientation error in **rad**, time in **ms**; **bold** marks the best (HJCD-IK) value. Open-world IK — Panda (Table I) ------------------------------- .. list-table:: :header-rows: 1 :stub-columns: 1 * - Batch - HJCD-IK Time - HJCD-IK Pos - HJCD-IK Ori - PyRoki Time - PyRoki Pos - PyRoki Ori - cuRobo Time - cuRobo Pos - cuRobo Ori - IKFlow Time - IKFlow Pos - IKFlow Ori * - 1 - **4.04** - 7.04e-2 - 2.04e-3 - 14.86 - 1.39e-2 - 1.12e-5 - 5.33 - 2.56e1 - 1.11e-1 - 18.48 - 4.67e0 - 2.28e-2 * - 10 - **3.82** - **1.21e-4** - **6.74e-7** - 14.62 - 1.39e-2 - 1.12e-5 - 5.55 - 2.49e-3 - 3.95e-6 - 18.95 - 1.38e0 - 6.21e-3 * - 100 - **4.07** - **2.25e-5** - **8.95e-8** - 14.20 - 1.39e-2 - 1.12e-5 - 6.01 - 9.16e-4 - 2.83e-6 - 22.29 - 5.94e-1 - 2.76e-3 * - 1000 - **4.22** - **1.60e-5** - **9.15e-8** - 13.96 - 1.39e-2 - 1.12e-5 - 19.80 - 3.67e-4 - 1.68e-6 - 49.78 - 2.06e0 - 5.43e-3 * - 2000 - **4.37** - **1.81e-5** - **5.15e-8** - 13.97 - 1.39e-2 - 1.12e-5 - 30.30 - 2.65e-4 - 1.33e-6 - 99.98 - 1.92e0 - 6.59e-3 Open-world IK — Fetch (Table I) ------------------------------- .. list-table:: :header-rows: 1 :stub-columns: 1 * - Batch - HJCD-IK Time - HJCD-IK Pos - HJCD-IK Ori - PyRoki Time - PyRoki Pos - PyRoki Ori - cuRobo Time - cuRobo Pos - cuRobo Ori - IKFlow Time - IKFlow Pos - IKFlow Ori * - 1 - **2.59** - 5.79e-1 - 1.20e-3 - 13.70 - 2.10e-5 - 3.12e-8 - 5.30 - 4.48e0 - 3.70e-3 - 17.40 - 1.92e1 - 6.67e-2 * - 10 - **2.41** - **1.40e-6** - **9.56e-9** - 13.48 - 2.10e-5 - 3.12e-8 - 5.52 - 6.74e-4 - 1.08e-6 - 16.36 - 9.60e0 - 3.66e-2 * - 100 - **2.52** - **1.67e-6** - **8.97e-9** - 13.16 - 2.10e-5 - 3.12e-8 - 7.57 - 1.61e-4 - 8.87e-7 - 19.75 - 1.65e1 - 7.24e-2 * - 1000 - **2.59** - **1.67e-6** - **6.10e-9** - 12.92 - 2.10e-5 - 3.12e-8 - 11.32 - 5.17e-5 - 6.43e-7 - 48.68 - 2.05e1 - 6.03e-2 * - 2000 - **2.73** - **1.66e-6** - **9.70e-9** - 13.37 - 2.10e-5 - 3.12e-8 - 14.62 - 3.96e-5 - 5.94e-7 - 87.89 - 1.52e1 - 4.87e-2 .. figure:: /_static/paper/pareto_batch.png :width: 100% :alt: Open-world accuracy–latency Pareto frontier across batch sizes Open-world accuracy–latency frontier (Table I) — HJCD-IK (orange), cuRobo (blue), PyRoki (green). Collision-free IK — Panda, box_panda (Table II) ----------------------------------------------- .. list-table:: :header-rows: 1 :stub-columns: 1 * - Batch - HJCD-IK Time - HJCD-IK Pos - HJCD-IK Ori - HJCD-IK Succ - PyRoki Time - PyRoki Pos - PyRoki Ori - PyRoki Succ - cuRobo Time - cuRobo Pos - cuRobo Ori - cuRobo Succ * - 1 - **5.44** - 8.17 - 1.96e-2 - 89.0 - 34.04 - 5.18e2 - 3.96e-1 - 6.0 - 23.76 - 7.85 - 2.61e-3 - 97.0 * - 10 - **4.19** - 7.11e-4 - 5.34e-7 - 98.0 - 46.29 - 9.90e-5 - 1.69e-7 - 89.0 - 29.31 - 2.43e-3 - 4.00e-6 - 100.0 * - 100 - **4.42** - **8.83e-5** - **3.56e-8** - **100.0** - 48.98 - 9.80e-5 - 1.41e-7 - 93.0 - 30.76 - 6.99e-4 - 2.00e-6 - 100.0 * - 1000 - **5.04** - **2.03e-5** - **9.06e-9** - **100.0** - 46.98 - 8.70e-5 - 1.36e-7 - 92.0 - 28.50 - 2.93e-4 - 2.00e-6 - 100.0 * - 2000 - **5.35** - **1.71e-5** - **7.16e-9** - **100.0** - 35.74 - 8.80e-5 - 1.49e-7 - 90.0 - 61.96 - 2.47e-4 - 2.00e-6 - 100.0 .. figure:: /_static/paper/pareto_collfree.png :width: 100% :alt: Collision-free accuracy–latency Pareto frontier Collision-free frontier on the *box_panda* scene (Fig. 4, Table II). .. note:: **Collision-free validation (methodology).** The benchmark harness reports a ``collision_free`` / ``success_both`` rate for every solver by validating each returned configuration *post-hoc* against the **same** 59-sphere Panda collision model HJCD-IK itself filters against (``benchmark/panda_collision.py``, sourced from the frozen paper model ``benchmark/reference/panda_collision_model.cuh``). HJCD-IK's kernel now filters via GRiD's URDF-driven ``grid_collision`` (the identical spheres, baked into ``grid.cuh`` from the foam spherized URDF), so this independent numpy oracle stays a fair cross-check. Because all solvers are judged by one shared geometry — not each tool's own collision notion — the column is apples-to-apples, and the check is pure-numpy (no cuRobo dependency). ``success_both`` is pose-success **and** collision-free. Regenerate with ``benchmark/baseline_bench.py --mode {pyroki,curobo} --collision_free`` (per-run CSV/YAML land under the gitignored ``benchmark/results/``; the time/accuracy numbers above are the camera-ready values). DoF scalability — Panda variants, B = 1000 (Table III) ------------------------------------------------------ .. list-table:: :header-rows: 1 :stub-columns: 1 * - DoF - HJCD-IK Time - HJCD-IK Pos - HJCD-IK Ori - PyRoki Time - PyRoki Pos - PyRoki Ori - cuRobo Time - cuRobo Pos - cuRobo Ori * - 7 - **4.25** - **1.71e-5** - **4.11e-8** - 15.09 - 2.63e-2 - 3.70e-5 - 9.11 - 3.38e-4 - 1.59e-6 * - 12 - **4.55** - **1.94e-5** - **6.91e-8** - 16.29 - 1.99e-2 - 1.86e-5 - 12.66 - 7.78e-1 - 2.57e-2 * - 18 - **4.62** - **3.76e-5** - **6.95e-8** - 20.82 - 2.15e-2 - 2.14e-5 - 16.26 - 8.41e-1 - 3.03e-2 * - 24 - **4.66** - **3.84e-5** - **7.32e-8** - 24.34 - 1.84e-2 - 1.99e-5 - 19.55 - 7.50e-1 - 3.58e-2 .. figure:: /_static/paper/pareto_dof.png :width: 100% :alt: DoF-scaling accuracy–latency Pareto frontier DoF scaling, 7–24 DoF (Fig. 5, Table III) — HJCD-IK keeps the lowest error and latency at every DoF. Solution diversity — MMD vs. TRAC-IK (Table IV) ----------------------------------------------- Maximum Mean Discrepancy between each solver's 50 best configurations (of a batch of 2000) and 50 ground-truth samples, over 100 target poses — lower is a closer match to the full IK manifold. .. figure:: /_static/paper/solution_distributions.png :width: 100% :alt: Distribution of collision-free IK solutions: cuRobo, PyRoki, HJCD-IK Distribution of collision-free IK solutions for a representative target — cuRobo (left), PyRoki (center), HJCD-IK (right). HJCD-IK returns a broader, more diverse spread of locally-optimal solutions. Reproducing these results ------------------------- The numbers above are the paper's; you can regenerate the **HJCD-IK** columns on your own GPU (absolute timings will differ — see the note at the top). The competitor baselines are optional and heavy. **One command (all tables, all installed solvers):** .. code-block:: bash ./scripts/setup/install_baselines.sh # optional: PyRoki, cuRobo, IKFlow, TRAC-IK (each skippable) RUN_DOF=1 RUN_MMD=1 ./scripts/bench/run_paper_experiments.sh # Tables I–IV + Pareto figures into benchmark/results/ # HJCD-IK only (no baselines): SKIP_CUROBO=1 SKIP_PYROKI=1 SKIP_IKFLOW=1 ./scripts/bench/run_paper_experiments.sh The baselines (PyRoki / cuRobo v2 / IKFlow / TRAC-IK) install behind the optional ``baselines`` extra plus some git/source steps; ``scripts/setup/install_baselines.sh`` handles each (and documents the per-solver gotchas — cuRobo's ``cuda-core`` backend, IKFlow's offline weights, TRAC-IK's ROS-free build). Each stage is independently skippable, and every solver runs the **same** shared open-world Halton targets for a fair comparison. **HJCD-IK on its own** (no baselines needed) — open-world or a collision-free MotionBenchMaker scene: .. code-block:: bash python benchmark/hjcd_ik_bench.py --skip-grid-codegen --batches 1,10,100,1000,2000 --num-targets 100 # collision-free (Panda box_panda, the paper's Table II scene): 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 The harness reports solved-rate, mean position / orientation error, and timing per batch size — the metrics ``tests/test_regression.py`` asserts against a committed baseline. Isolate timing runs (no concurrent GPU load). Per-robot end-effector frame ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The end-effector is a **named fixed-joint frame**, robot-specific. GRiD's codegen places it at an ``s_XmatsHom`` index that **shifts with DoF**, so ``scripts/codegen/generate_grid.py`` resolves that index and injects ``grid::EE_FIXED_FRAME_IDX`` into ``grid.cuh`` (``csrc/kernel/hjcd_settings.h`` consumes it — never hardcode the index). To switch robots: regenerate, then rebuild. .. list-table:: :header-rows: 1 * - Robot - URDF - ``-t`` target (fixed joint) - ``EE_FIXED_FRAME_IDX`` * - Panda 7-DoF - ``panda.urdf`` - ``panda_grasptarget_hand`` - 10 * - Panda 12-DoF - ``panda_ext_12dof.urdf`` - ``panda_hand_joint`` - 14 * - Panda 18-DoF - ``panda_ext_18dof.urdf`` - ``panda_hand_joint`` - 20 * - Panda 24-DoF - ``panda_ext_24dof.urdf`` - ``panda_grasptarget_hand`` - 27 * - Fetch 7-DoF - ``fetch.urdf`` - ``ee_fixed`` (→ ``ee_link``) - 7 .. code-block:: bash python scripts/codegen/generate_grid.py csrc/urdf/.urdf -t # injects EE_FIXED_FRAME_IDX bash scripts/setup/rebuild.sh # ninja + install (NOT ninja alone) The hardware results (Fig. 6) require the physical Franka Research 3 setup and are not reproducible from this repository. .. list-table:: :header-rows: 1 :stub-columns: 1 * - Metric - HJCD-IK - PyRoki - cuRobo - IKFlow * - MMD ↓ - **0.02261** - 0.04514 - 0.05348 - 0.03670 * - MMD² ↓ - **0.00051** - 0.00203 - 0.00286 - 0.00134