Skip to content

OpenArm Teaching Function Tutorial

Overview

The OpenArm teaching feature provides a full trajectory recording/playback system for bimanual robots.

  • Record trajectory: real-time recording of all joint states (both arms + both grippers)
  • Playback trajectory: accurate replay with speed scaling and selective playback
  • Multi-controller coordination: automatic synchronization of left arm, right arm, left gripper, and right gripper controllers

System Architecture

Based on ROS 2 Action interfaces, with two core modules:

1. Recording module (record_joint_states_always)

  • Subscribes to /joint_states and samples at fixed frequency
  • Supports interactive control (start/pause/clear/save)
  • Exports standard YAML trajectory files

2. Playback module (play_joint_trajectory)

  • Loads YAML trajectory and auto-groups joints
  • Uses FollowJointTrajectory Action for arms
  • Uses GripperCommand Action for grippers
  • Supports parallel multi-controller execution and time synchronization

Quick Start

Environment preparation

cd ~/openarmx_robotstride_ws-cc
colcon build --packages-select openarm_utils
source install/setup.bash

Step 1: Launch robot control system (MoveIt)

ros2 launch openarm_bimanual_moveit_config demo.launch.py

Step 2: Tune KP/KD

Since teaching requires manual repositioning, set KP/KD to low values.

Video in production, coming soon.

Step 3: Record trajectory

ros2 run openarm_utils record_joint_states_always --rate 20

Recording parameters

Parameter Description Default
--rate Sampling frequency (Hz) 10
--topic Joint state topic /joint_states
--outfile Output file path Auto-generated

Interactive controls

Key Function
SPACE or p Start/Pause
c Clear all recorded data (confirm required)
w Save and exit (confirm required)
q Exit without saving

Suggested sampling rates

  • Coarse motion: 5-10 Hz
  • General teaching: 10-20 Hz (recommended)
  • Fine manipulation: 20-50 Hz

Step 4: Playback trajectory

Playback all joints

ros2 run openarm_utils play_joint_trajectory joint_states_stream_20231215_143052.yaml --all-joints

Selective playback

ros2 run openarm_utils play_joint_trajectory <yaml_file> --left-arm
ros2 run openarm_utils play_joint_trajectory <yaml_file> --right-arm
ros2 run openarm_utils play_joint_trajectory <yaml_file> --both-arms
ros2 run openarm_utils play_joint_trajectory <yaml_file> --joints openarm_left_joint1 openarm_left_joint2

Playback parameters

Parameter Description Default
--all-joints Replay all joints Yes
--left-arm Left arm only No
--right-arm Right arm only No
--both-arms Both arms without grippers No
--joints Specific joints -
--rate-scale Playback speed scale 1.0
--action Specify single Action Auto detect
--sync-feedback Enable feedback sync No
--sync-margin Trigger lead time (s) 0.0

Speed control

ros2 run openarm_utils play_joint_trajectory <yaml_file> --all-joints --rate-scale 2.0
ros2 run openarm_utils play_joint_trajectory <yaml_file> --all-joints --rate-scale 0.5

Advanced Features

Multi-controller synchronization

Auto grouping

Joint prefix Controller Action type
openarm_left_joint* Left arm controller FollowJointTrajectory
openarm_right_joint* Right arm controller FollowJointTrajectory
openarm_left_finger* Left gripper controller GripperCommand
openarm_right_finger* Right gripper controller GripperCommand

Sync modes

ros2 run openarm_utils play_joint_trajectory <yaml_file> --all-joints
ros2 run openarm_utils play_joint_trajectory <yaml_file> --all-joints --sync-feedback
ros2 run openarm_utils play_joint_trajectory <yaml_file> --all-joints --sync-feedback --sync-margin 0.05

Single controller test

ros2 run openarm_utils play_joint_trajectory <yaml_file> --action /left_gripper_controller/gripper_cmd
ros2 run openarm_utils play_joint_trajectory <yaml_file> --action /right_joint_trajectory_controller/follow_joint_trajectory

Trajectory File Format

joint_names:
  - openarm_left_joint1
  - openarm_left_joint2
  - ...
points:
  - positions: [0.0, -0.5, 0.3, ...]
    time_from_start: 0.05

Practical Examples

Case 1: Bimanual coordinated grasp

ros2 run openarm_utils record_joint_states_always --rate 20
ros2 run openarm_utils play_joint_trajectory joint_states_stream_*.yaml --all-joints
ros2 run openarm_utils play_joint_trajectory joint_states_stream_*.yaml --all-joints --rate-scale 0.5

Case 2: Single-arm precise operation

ros2 run openarm_utils record_joint_states_always --rate 50
ros2 run openarm_utils play_joint_trajectory joint_states_stream_*.yaml --left-arm

Case 3: Gripper-only test

ros2 run openarm_utils record_joint_states_always --rate 10
ros2 run openarm_utils play_joint_trajectory joint_states_stream_*.yaml \
  --action /left_gripper_controller/gripper_cmd \
  --joints openarm_left_finger_joint1 openarm_left_finger_joint2