Configure ActionClient with joint_trajectory_controller/JointTrajectoryControllerfor ActionType: JOINT_TRAJECTORY#3
Configure ActionClient with joint_trajectory_controller/JointTrajectoryControllerfor ActionType: JOINT_TRAJECTORY#3munn33b wants to merge 2 commits intoycheng517:mainfrom
Conversation
ycheng517
left a comment
There was a problem hiding this comment.
@munn33b Appreciate you trying to contribute! However I don't think this PR is a step in the right direction. Feel free to prove me wrong.
Provides smoother, time-based motion for multi-DOF arms.
This approach should not result in smoother motion and but rather results in much worse responsiveness. Before ros2_control had the opportunity to update the currently executed trajectory to accomodate the new waypoint, now it can't since we wait for the previous trajectory to finish execution. When I tested this PR I could barely move my simulated arm, it was so slow and stuttery.
Enables proper trajectory execution instead of publishing raw position commands.
The new style has the same effect as publishing raw position commands. Under both styles we tell ros2 to go to a single waypoint.
lerobot_ros/robots/ros_interface.py
Outdated
| goal_msg.trajectory.points.append(point) | ||
|
|
||
| send_goal_future = self.traj_action_client.send_goal_async(goal_msg) | ||
| rclpy.spin_until_future_complete(self.robot_node, send_goal_future) |
lerobot_ros/robots/ros_interface.py
Outdated
| point.positions = joint_positions | ||
| msg.points = [point] | ||
| self.traj_cmd_pub.publish(msg) | ||
| point.time_from_start.sec = 1 # simple 1-second execution |
There was a problem hiding this comment.
You are absolutely right! The previous implementation was a blocking function that was running at 1 Hz means it would wait for previous waypoint and block the execution until that.
|
Thank you for taking the time to review and test the PR. I see your point about responsiveness and how waiting for the previous trajectory to complete prevents quick updates, which is not desirable for interactive teleoperation. My intention with introducing the JointTrajectoryController client was to move towards a more standards-compliant interface in ROS 2, since FollowJointTrajectory is widely used across many robot platforms and it introduces the Action Server. To properly integrate with this controller we need to utilize action client rather than relying solely on Raw Position commands publishing. This was the point of this pull request, I'll definitely work towards responsiveness and Update Frequency. |
|
This current update ensures that Control commands are sent at 60Hz to the Native Arm Trajectory Controller in ROS2 Control |
|
the 60Hz is happening via topics, which is what I was doing before. This PR effectively just implements what I've been doing, but with way more slop. |

This PR configures the ROS 2 ActionClient to communicate with joint_trajectory_controller/JointTrajectoryController using the FollowJointTrajectory action interface (control_msgs/action/FollowJointTrajectory).
🔧 Changes
Added support for ActionType: JOINT_TRAJECTORY.
Integrated joint_trajectory_controller/JointTrajectoryController into the robot config.
Updated ROS2Robot action client initialization to correctly use FollowJointTrajectory.
Ensured that teleop and other control modules can now send multi-joint trajectories instead of single position commands.
✅ Why this is needed
Enables proper trajectory execution instead of publishing raw position commands.
Provides smoother, time-based motion for multi-DOF arms.
Aligns with standard ROS 2 control patterns (ros2_control + joint_trajectory_controller).
📌 Testing
Verified that teleoperate.py can send keyboard/gamepad joint commands as trajectories.
Confirmed compatibility with a 6-DOF robot exposing position command interfaces.
No breaking changes for existing position-based control.