embodichain.compute#

Shared array and tensor computations#

compute owns numerical algorithms that operate on arrays, tensors, and kinematic parameters without importing the simulation runtime. It does not own robots, scenes, or environment lifecycle. Importing the root package does not load Torch or Warp. Domain packages load their required dependencies.

  • kinematics/_warp implements analytical OPW, SRS, and UR computations. Stateful solver interfaces remain in embodichain.lab.sim.motion.solvers.

  • trajectory provides the public tensor interfaces below. Its private _warp implementation supports path resampling and trajectory warping.

  • geometry/_warp/convex_query.py evaluates maximum halfspace values for convex hulls. These values classify containment; outside values are not generally exact Euclidean distances to the hull.

  • image/_warp/tiling.py converts tiled images into image batches.

Private _warp modules are implementation details, not a backend registry. Simulation-specific contact scattering belongs to embodichain.lab.sim.sensors._warp.contact.

Trajectory API#

interpolate_with_distance retains every required keyframe. resample_with_distance samples uniformly along cumulative path distance and may omit interior input samples. warp_trajectory_qpos changes a joint trajectory using interpolated offsets at supplied keyframes; warping here means trajectory deformation.

Use resample_with_distance(..., backend="torch") for dtype-preserving Torch resampling without entering Warp. The default auto path retains its float32 Warp implementation and Torch fallback. Both operate on batched paths; stationary paths and repeated endpoints remain valid inputs.

import torch
from embodichain.compute.trajectory import interpolate_with_distance

keyframes = torch.tensor([[[0.0], [1.0], [3.0]]])
result = interpolate_with_distance(keyframes, interp_num=5, device="cpu")
# result: [[[0.0], [0.5], [1.0], [2.0], [3.0]]]

differentiate_positions(positions, dt)

Estimate reference velocities using nonuniform three-point differences.

resample_in_time(positions, dt, sample_count)

Linearly sample a timed path on a uniform per-row time grid.

interpolate_with_distance(trajectory, interp_num)

Interpolate batched keyframes while preserving every keyframe boundary.

interpolate_minimum_jerk(trajectory, ...)

Interpolate joint keyframes with rest-to-rest minimum-jerk segments.

interpolate_with_nums(trajectory, interp_nums)

Interpolate each segment with its requested number of intervals.

resample_with_distance(trajectory, interp_num)

Resample a batched path at uniform cumulative-distance positions.

sort_and_padding_key_frame(trajectory, ...)

Sort keyframes and pad missing trajectory endpoints.

warp_trajectory_qpos(trajectory, ...[, device])

Apply interpolated keyframe offsets to batches of a joint trajectory.

Trajectory computations on arrays and tensors.

Interpolation retains keyframe boundaries; resampling treats interior points as optional path samples. Warping applies keyframe offsets to a trajectory.

Functions:

differentiate_positions(positions, dt)

Estimate reference velocities using nonuniform three-point differences.

interpolate_minimum_jerk(trajectory, ...)

Interpolate joint keyframes with rest-to-rest minimum-jerk segments.

interpolate_with_distance(trajectory, interp_num)

Interpolate batched keyframes while preserving every keyframe boundary.

interpolate_with_nums(trajectory, interp_nums)

Interpolate each segment with its requested number of intervals.

resample_in_time(positions, dt, sample_count)

Linearly sample a timed path on a uniform per-row time grid.

resample_with_distance(trajectory, interp_num)

Resample a batched path at uniform cumulative-distance positions.

retime_to_control_grid(positions, dt, control_dt)

Retimes a joint path to a fixed command period without speeding it up.

sort_and_padding_key_frame(trajectory, ...)

Sort keyframes and pad missing trajectory endpoints.

warp_trajectory_qpos(trajectory, ...[, device])

Apply interpolated keyframe offsets to batches of a joint trajectory.

embodichain.compute.trajectory.differentiate_positions(positions, dt)[source]#

Estimate reference velocities using nonuniform three-point differences.

Interior points use a time-weighted average of neighboring slopes; endpoints use one-sided differences. A zero-duration duplicate contributes no slope: use the other side if present, otherwise return zero. This handles rectangular padding without inventing a small time interval. This numerical operation does not impose rest boundaries or motion limits.

Parameters:
  • positions (Tensor) – Joint samples of shape (B, N, D).

  • dt (Tensor) – Arrival intervals of shape (B, N). The first interval is an arrival offset and does not participate in differentiation.

Return type:

Tensor

Returns:

Velocities with the positions’ shape, floating dtype and device.

Raises:

ValueError – For malformed/nonfinite inputs, negative intervals, or position changes at identical timestamps.

embodichain.compute.trajectory.interpolate_minimum_jerk(trajectory, minimum_sample_count, step_dt, velocity_limit, acceleration_limit)[source]#

Interpolate joint keyframes with rest-to-rest minimum-jerk segments.

minimum_sample_count is a lower bound. Each keyframe interval is expanded as needed so the analytic peak velocity and acceleration of the quintic time law stay within the scalar per-joint limits. Every input keyframe remains an exact output sample.

Parameters:
  • trajectory (Tensor) – Joint keyframes with shape (B, N, D).

  • minimum_sample_count (int) – Minimum total number of output samples.

  • step_dt (float) – Fixed output interval in seconds.

  • velocity_limit (float | Tensor) – Positive scalar or ordered per-joint velocity limits.

  • acceleration_limit (float | Tensor) – Positive scalar or ordered per-joint acceleration limits.

Return type:

Tensor

Returns:

Interpolated joint positions with a shared sample count for the batch.

Raises:

ValueError – If shapes, counts, timing, limits, or values are invalid.

embodichain.compute.trajectory.interpolate_with_distance(trajectory, interp_num, device=device(type='cuda'))[source]#

Interpolate batched keyframes while preserving every keyframe boundary.

Each input point is treated as a required keyframe. The output is generated segment by segment: every segment receives at least one interval, and any remaining intervals are distributed by Euclidean segment length for each batch independently. Segment endpoints are copied directly from the input, so intermediate keyframes occur as exact emitted samples.

Attention

interp_num must be at least the number of input keyframes. Use resample_with_distance() when input points are optional dense path samples that may be downsampled.

Parameters:
  • trajectory (Tensor) – Keyframe tensor with shape (B, N, M).

  • interp_num (int) – Target number of samples T.

  • device (device | str) – Device on which to perform interpolation.

Return type:

Tensor

Returns:

Interpolated trajectories with shape (B, T, M).

Raises:

ValueError – If trajectory is not three-dimensional, contains no keyframes for a non-empty output, or interp_num cannot hold all keyframes.

embodichain.compute.trajectory.interpolate_with_nums(trajectory, interp_nums, device=device(type='cuda'))[source]#

Interpolate each segment with its requested number of intervals.

The first keyframe is emitted once. Each positive count appends that many evenly spaced samples ending at the next keyframe. A zero count appends the next keyframe directly, so every original boundary is retained.

Parameters:
  • trajectory (Tensor) – Keyframe tensor with shape (B, N, M).

  • interp_nums (Tensor | Sequence[int]) – Non-negative interval counts with shape (N - 1,).

  • device (device | str) – Device on which to perform interpolation.

Return type:

Tensor

Returns:

A tensor containing the interpolated trajectories. For non-empty input, its sample count is 1 + sum(max(count, 1) for count in interp_nums).

Raises:

ValueError – If the count shape is invalid or a count is negative.

embodichain.compute.trajectory.resample_in_time(positions, dt, sample_count)[source]#

Linearly sample a timed path on a uniform per-row time grid.

Preserves the first arrival offset, endpoints and each row’s duration. Unlike distance resampling, dwell times and the sampled time profile affect interpolation. This does not certify continuous velocity/acceleration limits.

Parameters:
  • positions (Tensor) – Joint samples of shape (B, N, D), with N >= 1.

  • dt (Tensor) – Non-negative arrival intervals of shape (B, N).

  • sample_count (int) – Number of output samples, at least two.

Return type:

tuple[Tensor, Tensor]

Returns:

Positions (B, sample_count, D) and arrival intervals (B, sample_count), on the original device and with input dtypes.

Raises:

ValueError – For invalid timing, empty input paths, or fewer than two requested samples.

embodichain.compute.trajectory.resample_with_distance(trajectory, interp_num, device=device(type='cuda'), *, backend='auto')[source]#

Resample a batched path at uniform cumulative-distance positions.

Unlike interpolate_with_distance(), interior input samples are not required output points, so this function supports both upsampling and downsampling. It is intended for dense planner paths rather than required waypoint sequences.

The Warp implementation is used when available. A pure Torch reference path is used automatically when Warp has not been initialized, which keeps CPU-only callers and lightweight action tests functional.

Parameters:
  • trajectory (Tensor) – Path tensor with shape (B, N, M).

  • interp_num (int) – Target number of samples T.

  • device (device | str) – Device on which to perform interpolation.

  • backend (Literal['auto', 'torch']) – auto uses the existing float32 Warp path with a Torch fallback. torch uses only Torch, preserves floating-point dtype and never initializes Warp.

Return type:

Tensor

Returns:

Resampled trajectories with shape (B, T, M).

Raises:

ValueError – If trajectory is not three-dimensional, contains no points for a non-empty output, interp_num is negative, or backend is unknown.

embodichain.compute.trajectory.retime_to_control_grid(positions, dt, control_dt)[source]#

Retimes a joint path to a fixed command period without speeding it up.

Each row’s source duration T is quantized to ceil(T / control_dt) * control_dt. Positions are sampled at uniformly spaced phases of the source path, while returned arrival intervals use the fixed destination period. Shorter rows are padded with terminal holds.

Parameters:
  • positions (Tensor) – Joint samples with shape (B, N, D).

  • dt (Tensor) – Source arrival intervals with shape (B, N). The first interval must be zero.

  • control_dt (float) – Positive finite destination command period in seconds.

Return type:

tuple[Tensor, Tensor, Tensor, Tensor]

Returns:

Retimed positions, recomputed velocities, destination arrival intervals, and valid sample counts. The first and last valid velocity of every row are zero.

Raises:

ValueError – If the trajectory timing or destination period is invalid.

embodichain.compute.trajectory.sort_and_padding_key_frame(trajectory, key_indices, key_frames_batch)[source]#

Sort keyframes and pad missing trajectory endpoints.

Parameters:
  • trajectory (np.ndarray) – Original trajectory, shaped (N, DOF).

  • key_indices (np.ndarray) – Non-empty array of keyframe waypoint indices.

  • key_frames_batch (np.ndarray) – Target keyframes, shaped (B, K, DOF).

Returns:

padded and sorted key frame indices. [n_keyframe_new,] of int. key_frames_ascending (np.ndarray): padded and sorted batch key frames. [n_batch, n_keyframe_new, dof] of float.

Return type:

key_indices_ascending (np.ndarray)

embodichain.compute.trajectory.warp_trajectory_qpos(trajectory, key_indices, key_frames_batch, device='cuda')[source]#

Apply interpolated keyframe offsets to batches of a joint trajectory.

Parameters:
  • trajectory (torch.Tensor) – raw trajectory. [n_waypoint, dof] of float.

  • key_indices (torch.Tensor) – key frame waypoint indices. [n_keyframe,] of int.

  • key_frames_batch (torch.Tensor) – batch key frames. [n_batch, n_keyframe, dof] of float.

  • device (str, optional) – torch tensor device. Defaults to “cuda”.

Returns:

warped trajectory. [n_batch, n_waypoint, dof] of float.

Return type:

torch.Tensor

Timed trajectories use dt arrival intervals. differentiate_positions uses nonuniform central differences and one-sided endpoints, accepting only unchanged positions at repeated timestamps. It does not impose rest boundaries or motion limits. resample_in_time preserves endpoints and total duration while sampling the original time profile; callers must recompute derivatives after changing samples or timing.

Implementation modules#

Interpolate batched keyframes while preserving their boundaries.

Functions:

interpolate_minimum_jerk(trajectory, ...)

Interpolate joint keyframes with rest-to-rest minimum-jerk segments.

interpolate_with_distance(trajectory, interp_num)

Interpolate batched keyframes while preserving every keyframe boundary.

interpolate_with_nums(trajectory, interp_nums)

Interpolate each segment with its requested number of intervals.

embodichain.compute.trajectory.interpolation.interpolate_minimum_jerk(trajectory, minimum_sample_count, step_dt, velocity_limit, acceleration_limit)[source]#

Interpolate joint keyframes with rest-to-rest minimum-jerk segments.

minimum_sample_count is a lower bound. Each keyframe interval is expanded as needed so the analytic peak velocity and acceleration of the quintic time law stay within the scalar per-joint limits. Every input keyframe remains an exact output sample.

Parameters:
  • trajectory (Tensor) – Joint keyframes with shape (B, N, D).

  • minimum_sample_count (int) – Minimum total number of output samples.

  • step_dt (float) – Fixed output interval in seconds.

  • velocity_limit (float | Tensor) – Positive scalar or ordered per-joint velocity limits.

  • acceleration_limit (float | Tensor) – Positive scalar or ordered per-joint acceleration limits.

Return type:

Tensor

Returns:

Interpolated joint positions with a shared sample count for the batch.

Raises:

ValueError – If shapes, counts, timing, limits, or values are invalid.

embodichain.compute.trajectory.interpolation.interpolate_with_distance(trajectory, interp_num, device=device(type='cuda'))[source]#

Interpolate batched keyframes while preserving every keyframe boundary.

Each input point is treated as a required keyframe. The output is generated segment by segment: every segment receives at least one interval, and any remaining intervals are distributed by Euclidean segment length for each batch independently. Segment endpoints are copied directly from the input, so intermediate keyframes occur as exact emitted samples.

Attention

interp_num must be at least the number of input keyframes. Use resample_with_distance() when input points are optional dense path samples that may be downsampled.

Parameters:
  • trajectory (Tensor) – Keyframe tensor with shape (B, N, M).

  • interp_num (int) – Target number of samples T.

  • device (device | str) – Device on which to perform interpolation.

Return type:

Tensor

Returns:

Interpolated trajectories with shape (B, T, M).

Raises:

ValueError – If trajectory is not three-dimensional, contains no keyframes for a non-empty output, or interp_num cannot hold all keyframes.

embodichain.compute.trajectory.interpolation.interpolate_with_nums(trajectory, interp_nums, device=device(type='cuda'))[source]#

Interpolate each segment with its requested number of intervals.

The first keyframe is emitted once. Each positive count appends that many evenly spaced samples ending at the next keyframe. A zero count appends the next keyframe directly, so every original boundary is retained.

Parameters:
  • trajectory (Tensor) – Keyframe tensor with shape (B, N, M).

  • interp_nums (Tensor | Sequence[int]) – Non-negative interval counts with shape (N - 1,).

  • device (device | str) – Device on which to perform interpolation.

Return type:

Tensor

Returns:

A tensor containing the interpolated trajectories. For non-empty input, its sample count is 1 + sum(max(count, 1) for count in interp_nums).

Raises:

ValueError – If the count shape is invalid or a count is negative.

Resample batched paths at uniform cumulative-distance positions.

Functions:

resample_with_distance(trajectory, interp_num)

Resample a batched path at uniform cumulative-distance positions.

embodichain.compute.trajectory.resampling.resample_with_distance(trajectory, interp_num, device=device(type='cuda'), *, backend='auto')[source]#

Resample a batched path at uniform cumulative-distance positions.

Unlike interpolate_with_distance(), interior input samples are not required output points, so this function supports both upsampling and downsampling. It is intended for dense planner paths rather than required waypoint sequences.

The Warp implementation is used when available. A pure Torch reference path is used automatically when Warp has not been initialized, which keeps CPU-only callers and lightweight action tests functional.

Parameters:
  • trajectory (Tensor) – Path tensor with shape (B, N, M).

  • interp_num (int) – Target number of samples T.

  • device (device | str) – Device on which to perform interpolation.

  • backend (Literal['auto', 'torch']) – auto uses the existing float32 Warp path with a Torch fallback. torch uses only Torch, preserves floating-point dtype and never initializes Warp.

Return type:

Tensor

Returns:

Resampled trajectories with shape (B, T, M).

Raises:

ValueError – If trajectory is not three-dimensional, contains no points for a non-empty output, interp_num is negative, or backend is unknown.

Batched time-domain sampling and differentiation of joint trajectories.

Functions:

differentiate_positions(positions, dt)

Estimate reference velocities using nonuniform three-point differences.

resample_in_time(positions, dt, sample_count)

Linearly sample a timed path on a uniform per-row time grid.

retime_to_control_grid(positions, dt, control_dt)

Retimes a joint path to a fixed command period without speeding it up.

embodichain.compute.trajectory.timing.differentiate_positions(positions, dt)[source]#

Estimate reference velocities using nonuniform three-point differences.

Interior points use a time-weighted average of neighboring slopes; endpoints use one-sided differences. A zero-duration duplicate contributes no slope: use the other side if present, otherwise return zero. This handles rectangular padding without inventing a small time interval. This numerical operation does not impose rest boundaries or motion limits.

Parameters:
  • positions (Tensor) – Joint samples of shape (B, N, D).

  • dt (Tensor) – Arrival intervals of shape (B, N). The first interval is an arrival offset and does not participate in differentiation.

Return type:

Tensor

Returns:

Velocities with the positions’ shape, floating dtype and device.

Raises:

ValueError – For malformed/nonfinite inputs, negative intervals, or position changes at identical timestamps.

embodichain.compute.trajectory.timing.resample_in_time(positions, dt, sample_count)[source]#

Linearly sample a timed path on a uniform per-row time grid.

Preserves the first arrival offset, endpoints and each row’s duration. Unlike distance resampling, dwell times and the sampled time profile affect interpolation. This does not certify continuous velocity/acceleration limits.

Parameters:
  • positions (Tensor) – Joint samples of shape (B, N, D), with N >= 1.

  • dt (Tensor) – Non-negative arrival intervals of shape (B, N).

  • sample_count (int) – Number of output samples, at least two.

Return type:

tuple[Tensor, Tensor]

Returns:

Positions (B, sample_count, D) and arrival intervals (B, sample_count), on the original device and with input dtypes.

Raises:

ValueError – For invalid timing, empty input paths, or fewer than two requested samples.

embodichain.compute.trajectory.timing.retime_to_control_grid(positions, dt, control_dt)[source]#

Retimes a joint path to a fixed command period without speeding it up.

Each row’s source duration T is quantized to ceil(T / control_dt) * control_dt. Positions are sampled at uniformly spaced phases of the source path, while returned arrival intervals use the fixed destination period. Shorter rows are padded with terminal holds.

Parameters:
  • positions (Tensor) – Joint samples with shape (B, N, D).

  • dt (Tensor) – Source arrival intervals with shape (B, N). The first interval must be zero.

  • control_dt (float) – Positive finite destination command period in seconds.

Return type:

tuple[Tensor, Tensor, Tensor, Tensor]

Returns:

Retimed positions, recomputed velocities, destination arrival intervals, and valid sample counts. The first and last valid velocity of every row are zero.

Raises:

ValueError – If the trajectory timing or destination period is invalid.

Adjust joint trajectories using batches of keyframe offsets.

Functions:

sort_and_padding_key_frame(trajectory, ...)

Sort keyframes and pad missing trajectory endpoints.

warp_trajectory_qpos(trajectory, ...[, device])

Apply interpolated keyframe offsets to batches of a joint trajectory.

embodichain.compute.trajectory.warping.sort_and_padding_key_frame(trajectory, key_indices, key_frames_batch)[source]#

Sort keyframes and pad missing trajectory endpoints.

Parameters:
  • trajectory (np.ndarray) – Original trajectory, shaped (N, DOF).

  • key_indices (np.ndarray) – Non-empty array of keyframe waypoint indices.

  • key_frames_batch (np.ndarray) – Target keyframes, shaped (B, K, DOF).

Returns:

padded and sorted key frame indices. [n_keyframe_new,] of int. key_frames_ascending (np.ndarray): padded and sorted batch key frames. [n_batch, n_keyframe_new, dof] of float.

Return type:

key_indices_ascending (np.ndarray)

embodichain.compute.trajectory.warping.warp_trajectory_qpos(trajectory, key_indices, key_frames_batch, device='cuda')[source]#

Apply interpolated keyframe offsets to batches of a joint trajectory.

Parameters:
  • trajectory (torch.Tensor) – raw trajectory. [n_waypoint, dof] of float.

  • key_indices (torch.Tensor) – key frame waypoint indices. [n_keyframe,] of int.

  • key_frames_batch (torch.Tensor) – batch key frames. [n_batch, n_keyframe, dof] of float.

  • device (str, optional) – torch tensor device. Defaults to “cuda”.

Returns:

warped trajectory. [n_batch, n_waypoint, dof] of float.

Return type:

torch.Tensor

Kinematics API#

yoshikawa_manipulability returns sqrt(det(J @ J^T)) per batched Jacobian; condition_number returns the ratio of largest to smallest singular value. select_jacobian_rows extracts task-specific row subsets (for example the translational rows) before scoring. All operate on batched Torch tensors of shape (N, R, DOF) and preserve input dtype and device. Workspace analysis and IK candidate ranking share this single numerical implementation; aggregation stays in the consuming layer.

import torch
from embodichain.compute.kinematics import (
    select_jacobian_rows,
    yoshikawa_manipulability,
)

jacobians = torch.randn(8, 6, 7)
scores = yoshikawa_manipulability(jacobians)
translational = yoshikawa_manipulability(
    select_jacobian_rows(jacobians, "translational")
)

condition_number(jacobian[, eps])

Compute the Jacobian condition number sigma_max / sigma_min.

select_jacobian_rows(jacobian[, rows])

Select task-relevant rows of a batched spatial Jacobian.

yoshikawa_manipulability(jacobian)

Compute the Yoshikawa manipulability index sqrt(det(J @ J^T)).

Pure batched manipulability computations over robot Jacobians.

These helpers are the single numerical source shared by workspace analysis and IK candidate ranking. They operate on batched Torch tensors, preserve the input dtype and device, and never import simulation or workspace modules. Aggregation and result assembly belong to the consuming layers.

A Jacobian batch has shape (N, R, DOF) where R is 6 for a full spatial Jacobian; select_jacobian_rows() extracts task-specific row subsets (for example the translational rows) before scoring.

Functions:

condition_number(jacobian[, eps])

Compute the Jacobian condition number sigma_max / sigma_min.

select_jacobian_rows(jacobian[, rows])

Select task-relevant rows of a batched spatial Jacobian.

yoshikawa_manipulability(jacobian)

Compute the Yoshikawa manipulability index sqrt(det(J @ J^T)).

embodichain.compute.kinematics.manipulability.condition_number(jacobian, eps=1e-15)[source]#

Compute the Jacobian condition number sigma_max / sigma_min.

A large condition number marks an ill-conditioned (near-singular) posture whose manipulability ellipsoid is highly anisotropic.

Parameters:
  • jacobian (Tensor) – Batched Jacobian with shape (N, R, DOF).

  • eps (float) – Lower clamp on the smallest singular value to avoid division by zero; an exactly singular Jacobian yields a large finite ratio.

Return type:

Tensor

Returns:

Condition numbers with shape (N,), same dtype and device as jacobian.

Raises:

ValueError – If jacobian is not batched 3D.

embodichain.compute.kinematics.manipulability.select_jacobian_rows(jacobian, rows='all')[source]#

Select task-relevant rows of a batched spatial Jacobian.

Parameters:
  • jacobian (Tensor) – Batched Jacobian with shape (N, R, DOF).

  • rows (str | Sequence[int]) – "all" (default) keeps every row; "translational" keeps the linear-velocity rows (0, 1, 2); "rotational" keeps the angular-velocity rows (3, 4, 5); a sequence of ints selects exactly those row indices.

Return type:

Tensor

Returns:

The row-subset Jacobian with shape (N, len(rows), DOF).

Raises:

ValueError – If jacobian is not 3D, rows names an unknown selection, or a requested index is out of range.

embodichain.compute.kinematics.manipulability.yoshikawa_manipulability(jacobian)[source]#

Compute the Yoshikawa manipulability index sqrt(det(J @ J^T)).

The measure is the volume of the velocity manipulability ellipsoid. It is zero at singular configurations and positive elsewhere.

Parameters:

jacobian (Tensor) – Batched Jacobian with shape (N, R, DOF) (R <= DOF for a non-degenerate J @ J^T).

Return type:

Tensor

Returns:

Scores with shape (N,), same dtype and device as jacobian. The determinant is clamped at zero before the square root so numerical round-off near singularities never yields NaN.

Raises:

ValueError – If jacobian is not batched 3D.

Migration#

Existing imports from embodichain.utils.warp and its submodules continue to resolve to the relocated Warp kernel and struct objects. They do not register duplicate implementations. The legacy contact-kernel alias loads the simulation sensor package on demand.

Pure trajectory functions formerly defined in embodichain.lab.sim.utility.action_utils are re-exported there for compatibility. New consumers should import from compute.trajectory. get_trajectory_object_offset_qpos remains in the simulation utility module because it calls a stateful solver’s FK and IK interfaces.

Geometry tensor kernels#

Differentiable inverse kinematics#

The fixed-step DLS implementation preserves target and seed gradients through both FK and the geometric Jacobian. SerialChainKinematics adapts a copied PK chain without loading simulation. DifferentiableIKCfg configures the compute function and Torch layer; failed solves retain their last iterate.

damped_least_squares_step(error, jacobian, ...)

Compute J.T @ solve(J @ J.T + damping**2 I, error).

solve_dls_ik(target_xpos, qpos_seed, ...)

Unroll IK without detaching, early stopping, or shared scratch storage.

pose_error(current, target)

Return translation and shortest root-frame rotation residuals.

SerialChainKinematics

Own a PK chain without mutable per-call tensors or simulation objects.

DifferentiableIKCfg

Fixed-step DLS options shared by the compute API and Torch layers.

DifferentiableIKResult

Final iterate and root-frame TCP residuals, retaining their graphs.

Pure Torch DLS updates and fixed-step differentiable IK.

Functions:

damped_least_squares_step(error, jacobian, ...)

Compute J.T @ solve(J @ J.T + damping**2 I, error).

solve_dls_ik(target_xpos, qpos_seed, ...)

Unroll IK without detaching, early stopping, or shared scratch storage.

embodichain.compute.kinematics.dls.damped_least_squares_step(error, jacobian, damping)[source]#

Compute J.T @ solve(J @ J.T + damping**2 I, error).

Parameters:
  • error (Tensor) – Task error, shape (..., task_dim).

  • jacobian (Tensor) – Jacobian, shape (..., task_dim, dof).

  • damping (float) – Finite positive damping coefficient.

Return type:

Tensor

Returns:

Joint increment, shape (..., dof), preserving dtype and device.

embodichain.compute.kinematics.dls.solve_dls_ik(target_xpos, qpos_seed, kinematics, lower, upper, cfg)[source]#

Unroll IK without detaching, early stopping, or shared scratch storage.

Parameters:
  • target_xpos (Tensor) – Root-frame TCP targets, shape (..., 4, 4).

  • qpos_seed (Tensor) – Joint seed, shape (dof,) or (..., dof).

  • kinematics (Callable[[Tensor], tuple[Tensor, Tensor]]) – Maps flattened (N, dof) joints to TCP transforms and root-frame geometric Jacobians. Both outputs must be differentiable.

  • lower (Tensor) – Physical lower joint limits, shape (dof,).

  • upper (Tensor) – Physical upper joint limits, shape (dof,).

  • cfg (DifferentiableIKCfg) – Fixed-step solver configuration.

Return type:

DifferentiableIKResult

Returns:

Final iterate and residuals with the target’s leading batch dimensions. Failure returns the final iterate, never a detached seed fallback.

Note

All floating tensors must share dtype/device; inputs must be finite, targets must be rigid transforms, and lower limits cannot exceed upper. Success still checks physical limits when projection is disabled.

Finite-gradient SE(3) residuals for differentiable control.

Functions:

pose_error(current, target)

Return translation and shortest root-frame rotation residuals.

embodichain.compute.kinematics.pose_error.pose_error(current, target)[source]#

Return translation and shortest root-frame rotation residuals.

Parameters:
  • current (Tensor) – Achieved rigid transforms, shape (..., 4, 4).

  • target (Tensor) – Desired rigid transforms, broadcastable to current.

Return type:

tuple[Tensor, Tensor]

Returns:

Translation and axis-angle vectors, each with shape (..., 3).

Note

Inputs must be valid finite SE(3) transforms. The shortest rotation has a branch cut at pi; no unique smooth derivative exists there. The zero-rotation limit has finite first derivatives.

Simulation-independent serial-chain FK and TCP Jacobian adapter.

Classes:

SerialChainKinematics

Own a PK chain without mutable per-call tensors or simulation objects.

class embodichain.compute.kinematics.serial_chain.SerialChainKinematics[source]#

Own a PK chain without mutable per-call tensors or simulation objects.

Parameters:
  • chain (SerialChain) – Serial chain to copy. The caller’s model is never moved/mutated.

  • device (device | str) – Tensor device.

  • dtype (dtype) – Float32 for training or float64 for numerical validation.

Methods:

__init__(chain[, device, dtype])

evaluate(qpos, tcp)

Compute TCP transforms and geometric Jacobians using one FK pass.

from_urdf(urdf, end_link_name[, ...])

Build from URDF text; parsing and model construction happen once.

to(device, dtype)

Return a model copy on the requested device and precision.

__init__(chain, device='cpu', dtype=torch.float32)[source]#
evaluate(qpos, tcp)[source]#

Compute TCP transforms and geometric Jacobians using one FK pass.

Parameters:
  • qpos (Tensor) – Joint positions, shape (..., dof).

  • tcp (Tensor) – Flange-to-tool transforms, shape (4, 4) or (..., 4, 4).

Return type:

tuple[Tensor, Tensor]

Returns:

TCP poses (..., 4, 4) and root-frame Jacobians (..., 6, dof). Their backward paths include both FK and Jacobian derivatives.

classmethod from_urdf(urdf, end_link_name, root_link_name=None, *, device='cpu', dtype=torch.float32)[source]#

Build from URDF text; parsing and model construction happen once.

Parameters:
  • urdf (str) – URDF XML text, not a path.

  • end_link_name (str) – Controlled flange frame.

  • root_link_name (str | None) – Optional chain root frame.

  • device (device | str) – Tensor device.

  • dtype (dtype) – Tensor precision.

Return type:

SerialChainKinematics

Returns:

An independent serial-chain model.

to(device, dtype)[source]#

Return a model copy on the requested device and precision.

Return type:

SerialChainKinematics

Configuration and results for graph-preserving inverse kinematics.

Classes:

DifferentiableIKCfg

Fixed-step DLS options shared by the compute API and Torch layers.

DifferentiableIKResult

Final iterate and root-frame TCP residuals, retaining their graphs.

class embodichain.compute.kinematics.types.DifferentiableIKCfg[source]#

Fixed-step DLS options shared by the compute API and Torch layers.

Damping is strictly positive. Hard limit projection is piecewise differentiable and has zero gradients outside the projected interval. Tolerances only classify the final result; they never stop iterations.

Methods:

__init__([max_iterations, damping, ...])

copy(**kwargs)

Return a new object replacing specified fields with new values.

replace(**kwargs)

Return a new object replacing specified fields with new values.

to_dict()

Convert an object into dictionary recursively.

validate([prefix])

Check the validity of configclass object.

__init__(max_iterations=<factory>, damping=<factory>, step_size=<factory>, pos_eps=<factory>, rot_eps=<factory>, enforce_joint_limits=<factory>)#
copy(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

replace(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

to_dict()#

Convert an object into dictionary recursively.

Note

Ignores all names starting with “__” (i.e. built-in methods).

Parameters:

obj (object) – An instance of a class to convert.

Raises:

ValueError – When input argument is not an object.

Return type:

dict[str, Any]

Returns:

Converted dictionary mapping.

validate(prefix='')#

Check the validity of configclass object.

This function checks if the object is a valid configclass object. A valid configclass object contains no MISSING entries.

Parameters:
  • obj (object) – The object to check.

  • prefix (str) – The prefix to add to the missing fields. Defaults to ‘’.

Return type:

list[str]

Returns:

A list of missing fields.

Raises:

TypeError – When the object is not a valid configuration object.

class embodichain.compute.kinematics.types.DifferentiableIKResult[source]#

Final iterate and root-frame TCP residuals, retaining their graphs.

qpos#

Joint positions, shape (..., dof).

success#

Boolean convergence and physical-limit mask, shape (...).

position_error#

Target minus achieved translation, shape (..., 3).

rotation_error#

Shortest root-frame rotation vector, shape (..., 3).

Methods:

__init__(qpos, success, position_error, ...)

__init__(qpos, success, position_error, rotation_error)#