VnRoboVnRobo
AboutPricingBlogContact
🇻🇳VISign InStart Free Trial
🇻🇳VI
VnRobo logoVnRobo logo

AI infrastructure for next-generation industrial robots.

Product

  • Features
  • Pricing
  • Knowledge Base
  • Services

Company

  • About Us
  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 VnRobo. All rights reserved.

Made with♥in Vietnam
VnRoboVnRobo
AboutPricingBlogContact
🇻🇳VISign InStart Free Trial
🇻🇳VI
  1. Home
  2. Blog
  3. A ROS 2 bridge for cuRobo: from goal pose to JointTrajectory
manipulationcuroboros2jetsoncontrollertutorial

A ROS 2 bridge for cuRobo: from goal pose to JointTrajectory

Designing a ROS 2 wrapper around cuRobo with actions, lifecycle warmup, joint-state reordering, retiming, controller execution, and watchdogs.

Nguyen Anh TuanJune 5, 20262 min readUpdated: Oct 9, 2026
A ROS 2 bridge for cuRobo: from goal pose to JointTrajectory

Why wrap cuRobo with a ROS 2 action?

Planning has variable latency, can fail, and needs feedback. A ROS 2 action is a better fit than a service when goals need cancelation, progress, or timeout. The cuRobo node should be a lifecycle node: configure loads config, activate runs warmup, deactivate stops accepting goals.

Proposed interface

text
/curobo/plan_pose        action: PlanPose
/curobo/plan_grasp       action: PlanGrasp
/curobo/world            topic: PlanningScene
/joint_states            subscription
/arm_controller/follow_joint_trajectory action client
/curobo/status           topic: diagnostics

Avoid letting perception call the Python planner object directly in the same process unless you have handled the GIL, CUDA context ownership, and crash isolation. A dedicated planner process is easier to restart.

PlanPose action

text
geometry_msgs/PoseStamped goal_pose
string link_name
float32 max_planning_time
bool execute
---
bool success
string status
trajectory_msgs/JointTrajectory trajectory
---
string phase
float32 progress

ROS PoseStamped uses xyzw quaternions. The bridge must convert to wxyz before calling cuRobo.

Callback flow

python
def on_goal(goal):
    assert active
    joint_msg = wait_latest_joint_state(max_age=0.05)
    q = reorder_joint_state(joint_msg, curobo_joint_names)
    scene = latest_scene_snapshot()
    pose = ros_pose_to_curobo_pose(goal.goal_pose.pose)

    result = planner.plan_pose(q, pose, scene)
    if not result.success:
        return failed(result.status)

    traj = retime_and_clamp(result.interpolated_plan)
    if goal.execute:
        send_to_follow_joint_trajectory(traj)
    return success(traj)

Watchdogs and cancelation

Keep three timeouts separate:

Timeout Meaning
joint state age Do not plan from stale state
planning deadline Solver must not block callback forever
controller execution Robot must not execute forever

Canceling an action should cancel both the planner request and the controller goal. If the CUDA computation cannot be interrupted immediately, discard late results and never publish an old trajectory.

Retiming and clamps

cuRobo returns a smooth geometric trajectory, but hardware controllers need concrete limits:

python
for point in traj.points:
    point.velocities = clamp(point.velocities, velocity_limits)
    point.accelerations = clamp(point.accelerations, acceleration_limits)

If the robot arm has an internal controller, send sparser points and let it interpolate. If it only accepts raw setpoints, add spline or time parameterization in the bridge.

Diagnostics

Publish at least:

  • planner_ready;
  • cuda_memory_allocated;
  • last_plan_latency_ms;
  • last_plan_success;
  • last_failure_status;
  • joint_state_age_ms;
  • scene_age_ms.

Conclusion

The ROS 2 bridge is the safety boundary between a GPU optimizer and real hardware. With a clear interface, name-based joint reordering, quaternion conversion, and watchdogs, you can tune planner config without breaking the controller.

NT

Nguyễn Anh Tuấn

Robotics & AI Engineer. Building VnRobo — sharing knowledge about robot learning, VLA models, and automation.

Explore VnRobo

Fleet MonitoringROS 2 IntegrationAMR Solutions
curobo-jetson-g1 — Part 6/10
← Motion planning and grasping with cuRobo: obstacles, seedsScene mapping for cuRobo: depth cameras, TSDF/ESDF →

Related Posts

Tutorial
Motion planning and grasping with cuRobo: obstacles, seeds
curobomotion-planninggraspPart 5
manipulation

Motion planning and grasping with cuRobo: obstacles, seeds

Running pose-to-pose planning, obstacle collision, warmup, grasp approach-lift, and planner tuning for robot arms on Jetson.

6/1/20263 min read
NT
Tutorial
Installing cuRoboV2 on Jetson AGX Orin: CUDA and smoke tests
curobojetsoncudaPart 2
manipulation

Installing cuRoboV2 on Jetson AGX Orin: CUDA and smoke tests

A reproducible Jetson setup for cuRoboV2 with JetPack, uv, Python 3.11, CUDA 12.x, PyTorch, and deployment-focused checks.

5/20/20264 min read
NT
Tutorial
cuRobo on Jetson AGX Orin and Unitree G1: a 10-part roadmap
curobojetsonunitree-g1Part 1
manipulation

cuRobo on Jetson AGX Orin and Unitree G1: a 10-part roadmap

The opening guide for using cuRoboV2 on robot arms and Unitree G1, from Jetson runtime architecture to whole-body deployment boundaries.

5/16/20265 min read
NT
VnRobo logoVnRobo logo

AI infrastructure for next-generation industrial robots.

Product

  • Features
  • Pricing
  • Knowledge Base
  • Services

Company

  • About Us
  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 VnRobo. All rights reserved.

Made with♥in Vietnam