Add batched trapezoidal and Double-S trajectory planning - #566
Conversation
Greptile SummaryThe PR adds batched trapezoidal and Double-S trajectory planning across Torch and Warp, integrates continuous OPW Cartesian path IK, and expands tutorials, benchmarks, tests, and API documentation.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| embodichain/lab/sim/planners/trapezoidal_planner.py | Implements batched trapezoidal and Double-S profile construction, constraint projection, synchronization, and trajectory sampling. |
| embodichain/lab/sim/planners/trapezoidal_warp.py | Adds Warp kernels and wrappers for parallel profile construction, evaluation, and joint-space composition. |
| embodichain/utils/warp/kinematics/opw_solver.py | Adds temporally ordered OPW path branch selection with limit-aware periodic-equivalent handling. |
| embodichain/lab/sim/solvers/opw_solver.py | Exposes whole-path OPW IK and launches batched candidate generation and continuous selection. |
| embodichain/lab/sim/objects/robot.py | Adds the robot-level path-IK integration boundary used by Cartesian trajectory planning. |
| scripts/tutorials/sim/trapezoidal_planner.py | Demonstrates joint and Cartesian trajectory planning, timed replay, and trajectory diagnostics. |
Sequence Diagram
sequenceDiagram
participant Caller
participant Planner as TrapezoidalPlanner
participant Robot
participant OPW as OPWSolver
participant Warp
Caller->>Planner: Build Cartesian time law
Planner->>Robot: compute_ik_path(pose path, seed)
Robot->>OPW: get_ik_path(B,N,4,4)
OPW->>Warp: Generate all OPW candidates
Warp-->>OPW: Candidates and validity
OPW->>Warp: Select continuous branches over time
Warp-->>OPW: Path validity and joint path
OPW-->>Robot: Timed continuous joint samples
Robot-->>Planner: IK path result
Planner-->>Caller: PlanResult with explicit dt
Reviews (4): Last reviewed commit: "fix unittest" | Re-trigger Greptile
There was a problem hiding this comment.
Pull request overview
This PR introduces a new batched trajectory-planning capability (trapezoidal and jerk-limited Double‑S profiles) with Torch and Warp backends, integrates it into the existing MotionGenerator planner registry, and extends Cartesian straight-line planning with continuous batched IK path solving (notably for OPW via Warp).
Changes:
- Add
TrapezoidalPlanner(+ Warp backend) with constraint projection, synchronized multi-joint timing, and sampling (fixed-count / fixed-time). - Add continuous batched Cartesian path IK support (
Robot.compute_ik_path()andOPWSolver.get_ik_path()), plus tutorial + benchmark scripts. - Add comprehensive tests and update docs + agent context references.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/utils/test_opw_path_kernel.py | Adds a unit test validating OPW Warp path branch continuity selection. |
| tests/sim/planners/test_trapezoidal_planner.py | Adds extensive correctness/golden tests for trapezoidal and Double‑S planning across Torch/Warp. |
| tests/lab/scripts/test_trapezoidal_planner_tutorial.py | Tests tutorial utilities (Cartesian line planning, derivatives, plotting, replay behavior). |
| scripts/tutorials/sim/trapezoidal_profile.py | Adds a minimal scalar profile plotting example (no simulation). |
| scripts/tutorials/sim/trapezoidal_planner.py | Adds a full tutorial: joint + Cartesian planning, plotting diagnostics, and replay timing. |
| scripts/benchmark/motion_generation/trapezoidal_planner.py | Adds a reproducible Torch/Warp benchmark harness and markdown report output. |
| embodichain/utils/warp/kinematics/opw_solver.py | Adds a Warp kernel to select a temporally continuous OPW IK branch over a pose path. |
| embodichain/lab/sim/solvers/opw_solver.py | Adds OPWSolver.get_ik_path() to solve and continuously select an entire pose path in Warp. |
| embodichain/lab/sim/planners/trapezoidal_warp.py | Implements Warp profile construction and sampling kernels for the trapezoidal planner. |
| embodichain/lab/sim/planners/trapezoidal_planner.py | Adds the core batched trapezoidal/Double‑S planner (Torch reference + Warp dispatch). |
| embodichain/lab/sim/planners/motion_generator.py | Registers the new planner type and adds plan-options resolution for trapezoidal sampling. |
| embodichain/lab/sim/planners/init.py | Exports the new planner from the planners package. |
| embodichain/lab/sim/objects/robot.py | Adds Robot.compute_ik_path() for continuous pose-path IK through solver interfaces. |
| docs/source/overview/sim/solvers/opw_solver.md | Documents OPW whole-path IK behavior and kernels. |
| docs/source/api_reference/public_api.rst | Adds trapezoidal planner module to the public API autosummary list. |
| docs/source/api_reference/embodichain/embodichain.lab.sim.planners.rst | Adds API docs section and usage example for TrapezoidalPlanner. |
| agent_context/topics/motion-planning/motion-planning.md | Updates project context docs with the new planner and tutorial details. |
| agent_context/topics/ik-solvers/ik-solvers.md | Documents OPW whole-path IK behavior in the IK solvers overview. |
| agent_context/MAP.yaml | Extends motion-planning topic source-of-truth list with new modules/scripts. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
embodichain/lab/sim/objects/robot.py:1117
compute_ik_path()validates only the batch dimension/ndim forpose_tensor, but not the trailing matrix shape(4, 4)it promises in the docstring/error message. This can allow invalid inputs through and then fail later insidetorch.matmul/torch.inversewith a less clear error.
if pose_tensor.ndim != 4 or pose_tensor.shape[0] != batch_size:
raise ValueError("pose must have shape (B, N, 4, 4).")
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.
Suppressed comments (3)
Previously missed (2) — in code that hasn't changed since the last review.
embodichain/utils/warp/kinematics/opw_solver.py:533
- The kernel loops are hard-coded to 8 candidates and 6 joints (see
for candidate in range(8)/for joint in range(6)), but these parameter comments suggest a variableN_SOL/DOF. Please update the comments to reflect the fixed OPW sizes to avoid misleading future callers.
This issue also appears on line 537 of the same file.
full_ik_result: wp.array(dtype=float, ndim=4), # [B, N, N_SOL, DOF]
full_ik_valid: wp.array(dtype=int, ndim=3), # [B, N, N_SOL]
initial_seed: wp.array(dtype=float, ndim=2), # [B, DOF]
embodichain/lab/sim/planners/trapezoidal_warp.py:347
compose_profile_samples_warp()validates dtypes but not that all input tensors share the same device. If a caller accidentally mixes CPU/CUDA tensors, Warp will fail later with a less actionable error; adding an explicit device check here makes the public helper more robust (and matches the checks inbuild_profile_warp()).
)
if any(tensor.dtype != torch.float32 for tensor in tensors):
raise ValueError("The Warp trajectory backend requires float32 tensors.")
batch_size, sample_count = times.shape
embodichain/utils/warp/kinematics/opw_solver.py:538
path_resultis always 6-DOF (the kernel useswp_vec6flimits/weights and loopsfor joint in range(6)), but the comment saysDOF. Align this with the fixed OPW DOF to keep the signature self-documenting.
path_result: wp.array(dtype=float, ndim=3), # [B, N, DOF]
path_valid: wp.array(dtype=int, ndim=2), # [B, N]
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
embodichain/lab/sim/objects/robot.py:1117
compute_ik_path()validates only the batch dimension and rank forpose, but not the trailing matrix shape. If a caller passes(B, N, 7)or(B, N, 3, 4)the error message claims(B, N, 4, 4)yet the check passes and the subsequentmatmul/inversewill fail with a less clear runtime error. Tighten the shape check to includepose_tensor.shape[-2:] == (4, 4).
if pose_tensor.ndim != 4 or pose_tensor.shape[0] != batch_size:
raise ValueError("pose must have shape (B, N, 4, 4).")
Review against the current
|
| @@ -0,0 +1,854 @@ | |||
| # ---------------------------------------------------------------------------- | |||
There was a problem hiding this comment.
Recommended to add a new folder to put all planner tutorial together or move these two files to examples/sim/planner
| @@ -0,0 +1,399 @@ | |||
| # ---------------------------------------------------------------------------- | |||
There was a problem hiding this comment.
For kernel-only module, we should put them into embodichain/utils/warp/kinematics
Description
This PR adds a batched trajectory planner supporting trapezoidal velocity and jerk-limited seven-phase Double-S motion profiles.
The planner supports both Torch and NVIDIA Warp backends and integrates with the existing MotionGenerator interface. The Warp backend parallelizes scalar profile construction, phase evaluation, and batched joint trajectory
composition.
It also adds Cartesian straight-line trajectory planning for the simulation tutorial. Cartesian distance is time-parameterized before IK, ensuring the requested end-effector path follows the configured velocity, acceleration, and
jerk constraints.
For OPW-based robots, the complete Cartesian pose path is now solved through a batched Warp path-IK interface:
This avoids launching OPW IK separately for every trajectory sample while preserving joint-path continuity.
Additional changes include:
Add TrapezoidalPlanner, TrapezoidalPlannerCfg, and TrapezoidalPlanOptions.
Support scalar and per-joint velocity, acceleration, and jerk limits.
Support synchronized multi-joint motion.
Support triangular fallback for short trapezoidal moves.
Support seven-phase Double-S profiles without display filtering.
Support fixed-count and fixed-time trajectory sampling.
Support optional minimum-duration scaling.
Support redundant collinear waypoint compression.
Add explicit torch, warp, and auto backend selection.
Add continuous Cartesian path IK through Robot.compute_ik_path().
Add batched OPW path solving through OPWSolver.get_ik_path().
Compute Cartesian joint velocity and acceleration using the path time law and differential kinematics rather than numerical time differentiation.
Add simulation replay using the planned trajectory timing.
Add diagnostic plots for:
Add standalone profile and simulation tutorials.
Add a reproducible Torch/Warp trajectory-planner benchmark.
Update motion-planning, solver, and API documentation.
Motivation and context:
The existing trajectory-planning examples primarily relied on TOPPRA and did not provide a lightweight, natively batched implementation for trapezoidal or jerk-limited motion profiles.
Cartesian trajectories also require the time law to be applied in Cartesian space before IK. Applying joint-space timing after independently sampled IK can distort the requested end-effector path and produce inconsistent
derivatives.
This change provides a maintainable trajectory-planning implementation suitable for both CPU execution and large batched CUDA workloads, while keeping Torch as the reference and fallback backend.
Dependencies:
Fixes #
Type of change
Screenshots
The trajectory tutorial displays a diagnostic dashboard containing the Cartesian path, XYZ position, orientation, joint position, joint velocity, and joint acceleration.
Joint trajectory Cartesian straight-line trajectory
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Attach the joint-space trajectory screenshot here Attach the Cartesian Double-S trajectory screenshot here
Example command used for the Cartesian screenshot:
python scripts/tutorials/sim/trapezoidal_planner.py
--path cartesian
--profile acceleration_trapezoidal
--backend warp
--cartesian-distance 0.10
--cartesian-step 0.005
--cartesian-velocity 0.15
--cartesian-acceleration 0.30
--cartesian-jerk 1.0
--replay-speed 0.5
Validation
The following focused validation was completed: