Solver kernel#

The batched HJCD solver: block-cooperative coarse search, then warp-per-candidate Levenberg–Marquardt refinement.

The native host API lives in csrc/kernel/hjcd_kernel.h. Both sampling and solving serialize access to shared CUDA constants and stop flags. Python releases the GIL while these operations run. Models and joint limits are cached per CUDA device; callers must keep the CUDA context alive (calling cudaDeviceReset invalidates those caches).

Result<T> owns its host arrays, releases them on destruction, and supports moves but not copies. Temporary device allocations are released on normal return and exceptions. HJCD CUDA runtime failures raise std::runtime_error (Python RuntimeError), including generated model/limit initialization. HJCD uses GRiD’s checked APIs: initialization failures report the operation, roll back partial allocations best-effort, and never reset the CUDA context or terminate the process. This does not promise recovery after a context-invalidating CUDA error.

A null model argument selects the internally cached model for sampling. The solver selects its own coarse/refine models by precision; its model argument is retained for source compatibility. Position errors are in millimeters and orientation errors in radians.

Defines

PI#

Functions

template<typename T>
std::array<T, 7> normalized_target_pose(const T *pose)#
template<typename T, typename RT = double>
Result<T> generate_ik_solutions(T *target_pose, const grid::robotModel<T> *d_robotModel, int b_size, int num_solutions = 1, bool collision_free = false, const char *problems_json_text = nullptr, const char *problem_set_name = nullptr, int problem_idx = 0, bool write_stats = false, int collision_mode = -1)#

Solve one end-effector target with a GPU batch of candidate configurations.

Compiled instantiations are <double,double>, <double,float>, and <float,double>. T controls I/O; RT controls LM compute precision; coarse search always uses float. Calls serialize shared native state on the calling thread’s current CUDA device. Cached models require that context to remain alive; cudaDeviceReset is unsupported.

Parameters:
  • target_pose – Nonnull seven-vector [x,y,z,qw,qx,qy,qz], meters and scalar-first quaternion. Finite nonzero quaternions are normalized without mutating this input.

  • d_robotModel – Retained for source compatibility; ignored. Precision-specific internally cached generated models are used by the solver.

  • b_size – Positive candidate count (not a target count), bounded by CUDA indexing.

  • num_solutions – Positive maximum number of distinct candidates requested.

  • collision_free – Enable post-solve collision processing; requires a collision build.

  • problems_json_text – MotionBenchMaker-style JSON, required with collision_free.

  • problem_set_name – Key under the JSON “problems” object.

  • problem_idx – Nonnegative index within the selected problem set.

  • write_stats – Append diagnostics to ik_stats.csv; write failures throw.

  • collision_mode – 0 = environment-only soft ranking, 1 = hard self/environment filtering, 2 = both; -1 reads HJCD_CC_MODE (defaults to hard). Ignored in open-world solves.

Throws:
  • std::invalid_argument – For invalid scalar/pose values.

  • std::runtime_error – For checked CUDA or output failures. Scene errors also throw. Generated model/limit initialization uses GRiD’s checked APIs and raises on failure.

Returns:

Owning result. Candidates may be approximate, fewer than requested, or empty. Collision checks describe configurations, never paths.

template<typename T>
std::vector<std::array<T, 7>> sample_random_target_poses(const grid::robotModel<T> *d_robotModel, int num_configs, std::uint64_t seed)#

Sample reachable world-frame poses from a seeded Halton joint sequence.

T may be float or double. The result uses [x,y,z,qw,qx,qy,qz], meters and scalar-first quaternions. Sampling respects joint limits but does not check collision. Calls share the solver lock and use the calling thread’s current CUDA device.

Parameters:
  • d_robotModel – Device model matching the compiled robot and T, or nullptr for the cache.

  • num_configs – Positive target count bounded by CUDA launch indexing.

  • seed – Unsigned seed used to shift the Halton sequence.

void init_joint_limits_from_grid()#

Lazily initialize generated joint limits on the current device; normally called internally.

int grid_num_joints()#

Return the compiled actuated joint count without initializing CUDA.

bool grid_has_collision()#

Return whether the compiled header includes collision geometry, without initializing CUDA.

template<typename T>
struct Result#
#include <hjcd_kernel.h>

Move-only owner of a native solve’s row-major host buffers.

Read only the first count rows. A returned candidate is not a success certificate: check both error arrays against your tolerances. Collision filtering can yield count == 0. Buffers remain valid until this object is reset, destroyed, or moved from. Do not delete the individual pointers; ownership follows the Result object.

Public Functions

Result() = default#
inline ~Result()#
Result(const Result&) = delete#
Result &operator=(const Result&) = delete#
inline Result(Result &&other) noexcept#
inline Result &operator=(Result &&other) noexcept#
inline void reset() noexcept#

Release all owned buffers and restore the empty state; safe to call repeatedly.

Public Members

T *joint_config = nullptr#

count x grid_num_joints() joint angles, radians.

T *pose = nullptr#

count x 7 poses: [x,y,z,qw,qx,qy,qz], positions in meters.

T *pos_errors = nullptr#

count position errors, millimeters.

T *ori_errors = nullptr#

count orientation errors, radians.

T elapsed_time = {}#

Host-observed solve duration, milliseconds (not per candidate).

int count = 0#

Number of returned candidates, possibly less than requested.

namespace grid#

Functions

template<typename T>
robotModel<T> *init_robotModel()#