Skip to content

Moving Joints

There are two ways to move joints in the simulation: the Joint GUI (graphical, interactive) and the move_joints CLI node (scriptable, one-shot commands).

Both publish JointTrajectory messages to the joint_trajectory_controller.

The Joint GUI launches automatically with the simulation. It provides sliders for each joint discovered from the robot’s URDF.

ButtonAction
SendPublishes the current slider positions as a trajectory command
SyncReads current joint positions from /joint_states and moves sliders to match
ResetZeros all sliders

You can also:

  • Change the Duration (seconds) for how long the trajectory takes
  • Select which Topic to publish on (auto-discovered from available JointTrajectory topics)
  • Click Refresh to re-scan for topics
  1. On launch, the GUI parses the URDF file for all revolute joints, reading their lower and upper limits
  2. It subscribes to /joint_states to discover which joints are actually active and their starting positions
  3. When you hit Send, it publishes a JointTrajectory message to the selected topic with positions offset by each joint’s origin angle

The move_joints node sends a single trajectory command and exits. It’s useful for scripting or quick tests.

Inside devcontainer
ros2 run sim_common move_joints --ros-args \
-p joints:="['shoulder_1', 'elbow_1', 'wrist_1', 'wrist_2']" \
-p positions:="[0.5, 0.5, 0.2, 0.0]" \
-p duration:=2.0
ParameterRequiredDefaultDescription
jointsYesList of joint names to move
positionsYesTarget positions (radians), one per joint
durationNo2.0Seconds to reach the target
topicNoSee belowTrajectory topic to publish on

Default topic: /joint_trajectory_controller/joint_trajectory

The node:

  1. Creates a publisher on the trajectory topic
  2. Waits (polling every 0.5s) until at least one subscriber is connected
  3. Publishes the trajectory message
  4. Logs the command and exits

This means the joint trajectory controller must be running before move_joints can send its command. If you run it right after launching the simulation, it will wait automatically until the controller is ready.

Inside devcontainer
ros2 run sim_common move_joints --ros-args \
-p joints:="['shoulder_1', 'elbow_1']" \
-p positions:="[1.0, -0.5]" \
-p duration:=3.0
Inside devcontainer
ros2 run sim_common move_joints --ros-args \
-p joints:="['wrist_1']" \
-p positions:="[0.8]" \
-p duration:=5.0