Trajopt_plan_cspace ~0.5–1.0s on RTX 4050 (Windows) — expected latency for standalone TrajOpt?

Title: trajopt_plan_cspace ~0.5–1.0s on RTX 4050 (Windows) — expected latency for standalone TrajOpt?

Hi,

I’m integrating cuMotion TrajOpt directly via the C++ API (TrajectoryOptimizer::planToCSpaceTarget / trajopt_plan_cspace), not the full Isaac ROS motion planner (no graph search, no NVBlox). I’d like to understand whether our planning latency is expected, and which parameters matter most for a standalone c-space TrajOpt call.

Environment

  • GPU: Laptop RTX 4050 (Windows)
  • cuMotion: 1.1.0 (CUDA 13, prebuilt Windows x86_64)
  • Robot: Custom 5-DOF manipulator (tube / Transhift), URDF + XRDF collision spheres
  • World: Static virtual walls from safe-zone union (cuboids), world collision enabled (default), self-collision disabled
  • API: CreateDefaultTrajectoryOptimizerConfig → CreateTrajectoryOptimizer → planToCSpaceTarget(q_start, q_target) per segment
  • Post-processing: Sample TrajOpt output at 125 Hz only; no post-TrajOpt retime / TrajGen

Config (mostly cuMotion defaults)
We do not override most TrajOpt params in our app config:

  • trajopt/num_knots_per_trajectory: default (32)
  • trajopt/num_seeds: default (4) — not exposed in our Rust wrapper yet
  • trajopt/pbo/enabled: default (true)
  • ik/num_seeds, ik/max_reattempts: default (c-space targets; IK may be less relevant)
  • enable_self_collision: false
  • enable_world_collision: default (true)
  • App-level trajopt_retries: 1 on success path (tests use 16)

Measured timing (single segment, 2 waypoints, 1 attempt, Success)

Case | j0 travel | c-space path length | trajopt_setup | trajopt_solve | total plan
Easier | 58 mm | 2.21 | ~124 ms | ~492 ms | ~617 ms
Easier (rev) | 58 mm | 2.23 | ~138 ms | ~563 ms | ~701 ms
Harder | 146 mm (detour/walls) | 3.09 | ~134 ms | ~1004 ms | ~1140 ms

Notes:

  • trajopt_solve dominates (~80–88% of plan time).
  • trajopt_setup (~130 ms) is from recreating optimizer config + CreateTrajectoryOptimizer on every attempt/segment.
  • Sampling 400–480 knots at 125 Hz is <1 ms (not the bottleneck).

Failure case (separate issue)
When start/goal are near zone boundaries, we sometimes get GeometricPlanningFailure and with trajopt_retries=16 total time reaches ~30+ s (~2 s per failed attempt). I understand that’s a different problem from the successful ~1 s case.

Questions

  1. For standalone planToCSpaceTarget (no graph planner), is ~0.5–1.0 s on a desktop RTX 4050 expected with default TrajOpt config (4 seeds, PBO on, 32 knots, world collision)?
  2. The cuRobo blog mentions ~100 ms median motion planning on Jetson Orin — does that benchmark include the full motion generation pipeline (graph + TrajOpt), and is it not directly comparable to a single TrajOpt c-space call with virtual walls?
  3. For fastest c-space TrajOpt while keeping world collision, which parameters should we tune first?
    • trajopt/num_seeds
    • trajopt/pbo/enabled, num_particles_per_problem, num_iterations
    • trajopt/num_knots_per_trajectory
    • L-BFGS iteration limits (initial_iterations, retiming_*)
  4. Is trajopt/num_seeds=4 still applied for c-space targets (linear interpolation seeds), or mainly for task-space IK seeds?
  5. Any recommendation on reusing TrajectoryOptimizer across plans vs rebuilding each time (we pay ~130 ms setup per call)?

Happy to provide URDF/XRDF snippets, safe-zone wall setup, or a minimal repro if helpful.

Thanks!

Hello @laplacehurt,

Welcome to the Isaac ROS forum and thanks for the detailed timing breakdown.

To get lower planning latency, try not to recreate the config and optimizer for every segment. Also double-check that use_cuda_path is still set to True.
The recommended pattern is like below:

  • CreateDefaultTrajectoryOptimizerConfig()
  • set/verify use_cuda_graph = true
  • CreateTrajectoryOptimizer() once
  • run one warmup plan
  • reuse the same TrajectoryOptimizer for each planToCSpaceTarget() query
// Init once
auto config = CreateDefaultTrajectoryOptimizerConfig(...);

// Exact field name depends on cuMotion 1.1.0 C++ API.
// If exposed, keep/enable CUDA graph:
config.trajopt.use_cuda_graph = true;

config.trajopt.num_knots_per_trajectory = 32;
config.trajopt.num_seeds = 4;
config.trajopt.pbo.enabled = true;

auto optimizer = CreateTrajectoryOptimizer(config);

// Warmup once, not included in timing
optimizer->planToCSpaceTarget(q_start_dummy, q_goal_dummy);

// Runtime loop, can be reuse for real queries
for (const auto& segment : segments) {
    auto result = optimizer->planToCSpaceTarget(segment.q_start, segment.q_goal);
}

Keep the problem shape stable after the first call: same planner type, batch size, seed count, knot count, robot model, and preferably same collision-world structure. Only recreate the CUDA graph if the above setting change.

The ~100 ms cuRobo record that you mentioned might not be directly comparable to this standalone planToCSpaceTarget case. Those benchmark paths are generally MotionGen / planner benchmarks, not “single cold standalone TrajOpt C-space call with custom virtual cuboid walls on X86 desktop.” MotionGen may include IK for Cartesian targets and can fall back to graph planning when linear TrajOpt seeds are not enough, but your case is direct C-space TrajOpt with no graph planner.

If you want to try tuning parameters, you could try adjusting below items:
Reduce trajopt/num_seeds from 4 to 2 or 1 for easy paths.
Reduce or disable PBO / particle optimization if linear C-space seeds are usually feasible.
Reduce num_knots_per_trajectory from 32 to 24 or 16, then verify collision clearance.
Reduce L-BFGS / retiming iteration limits last, because this can hurt robustness and solution quality.

trajopt/num_seeds=4 should still matter for C-space targets. It is separate from IK seeds. IK seeds mainly apply to Cartesian pose targets, while C-space planning still uses trajectory seeds, such as linear/interpolated seeds, for TrajOpt.