Custom robot (GRiD codegen workflow)#
HJCD-IK’s kinematics are generated from a URDF by GRiD into csrc/generated/grid.cuh.
Install the codegen dependencies first: python -m pip install -e '.[codegen]'.
Each wheel contains one robot model; switching a Python variable or URDF filename at
runtime does not change the compiled solver. Check hjcdik.build_info() after rebuilding.
Regenerate grid.cuh#
python scripts/codegen/generate_grid.py path/to/robot.urdf -t <ee_target_frame>
-tselects a fixed end-effector target frame attached to the final actuated joint (e.g.panda_grasptarget_hand).Output is the stock generated header — never hand-edit it.
Robot constants (
NUM_JOINTS, topology counts) are baked per-URDF; the solver reads them from the generated symbols, so don’t hardcode sizes.
Then rebuild: python -m pip install -e ..
Source archives without Git metadata#
Pass --glass-revision <full-commit-sha> to label generated headers from a source
archive, or set GRID_GLASS_REVISION (also honored by the header-freshness check).
Use the nested GLASS revision recorded for that source release, not an unrelated
top-level checkout. With Git present, GRiD rejects a label that disagrees with the
nested checkout; without Git it explicitly reports the supplied label as unverified.
This preserves byte-identical generation without weakening freshness checks.
Isolated native builds#
Generate into a separate directory to keep the checkout’s default Panda model intact. For example, to build and test the bundled Fetch arm:
model_dir=$(mktemp -d /tmp/hjcd-fetch.XXXXXX)
python scripts/codegen/generate_grid.py csrc/urdf/fetch.urdf -t ee_fixed -o "$model_dir/grid.cuh"
cmake -S . -B "$model_dir/build" -DBUILD_PYTHON=OFF \
-DHJCDIK_GRID_HEADER="$model_dir/grid.cuh" -DHJCDIK_BUILD_NATIVE_TESTS=ON
cmake --build "$model_dir/build" --parallel 2
ctest --test-dir "$model_dir/build" --output-on-failure
HJCDIK_GRID_HEADER must point to a generated file named grid.cuh. Each build directory
selects its own robot; use different directories for different models. Automatic codegen is
an opt-in (HJCDIK_AUTO_CODEGEN=ON) restricted to the default Panda workflow; generate
custom headers explicitly. Ordinary builds use the committed header without regeneration.
For a Python wheel, pass the same option through scikit-build-core and select a separate build directory:
python -m pip wheel . --no-deps -Cbuild-dir="$model_dir/python-build" \
-Ccmake.define.HJCDIK_GRID_HEADER="$model_dir/grid.cuh" -w "$model_dir/wheels"
The wheel contains that one compiled robot. Install it in a separate virtual environment when
comparing robots. Base CUDA architecture defaults to the available GPU; CUDAARCHS or
-DCMAKE_CUDA_ARCHITECTURES=... can override it for cross-compilation.
Collision (bring-your-own-URDF)#
Add --collision to bake GRiD’s grid_collision spheres (and self-collision ranges) into the same
grid.cuh — no hand-written per-robot collision code:
# spherize the URDF's own collision meshes:
python scripts/codegen/generate_grid.py path/to/robot.urdf -t <ee_target> --collision --collision-res 0.05
# or read a pre-spherized foam URDF (when the URDF's meshes don't resolve on disk, e.g. Panda):
python scripts/codegen/generate_grid.py path/to/robot.urdf -t <ee_target> --collision --spherized-urdf path/to/robot_spherized.urdf
Caveats#
HJCD-IK currently supports fixed-base serial chains with 1–32 independent revolute or continuous joints, each rotating around its local +Z axis. Fixed joints may connect the links and tool frame. GRiD supports more general robots, but this solver’s geometric Jacobian and suffix FK do not; codegen rejects floating bases, branches, mimic joints, prismatic joints, and other joint axes.
The default codegen profile emits kinematics and optional collision only. Use
--profile allonly when the generated header is also needed by an external dynamics consumer.Without
--collisionthe build runs open-world; the Python API rejectscollision_free=True(the collision path is compiled out via theHJCD_HAS_COLLISIONsentinel).Keep the EE-target frame consistent with
FLANGE_IDXusage in the kernel.