Skip to content

SDK Interfaces

RobotInterface is the abstract base class for all robot integrations. It is responsible for:

  • Creating a ROS2 node (node name rl_deploy)
  • Providing robot state reading interfaces
  • Providing joint command sending interfaces
  • Providing extended reading interfaces for battery, IMU, temperature, etc.
RobotInterface(const std::string& robot_name, int dof_num)
virtual VecXf GetJointPosition() = 0; // Get 12 joint positions
virtual VecXf GetJointVelocity() = 0; // Get 12 joint velocities
virtual VecXf GetJointTorque() = 0; // Get 12 joint torques
virtual Vec3f GetImuRpy() = 0; // Get IMU roll/pitch/yaw angles
virtual Vec3f GetImuAcc() = 0; // Get IMU 3-axis acceleration
virtual Vec3f GetImuOmega() = 0; // Get IMU 3-axis angular velocity
virtual VecXf GetContactForce() = 0; // Get quadruped foot-end contact forces
virtual void SetJointCommand(Eigen::Matrix<float, Eigen::Dynamic, 5> input) = 0;

The input matrix has 5 columns per row corresponding to: kp, goal_angle_pos, kd, goal_vel, torque_feedforward.

DdsInterface is the ROS2 topic connection implementation. It subscribes to robot feedback and publishes joint commands.

joint_cmd_pub_ = node_->create_publisher<drdds::msg::JointsDataCmd>("/JOINTS_CMD", 10);
// Publish joint control commands
joint_data_sub_ = node_->create_subscription<drdds::msg::JointsData>("/JOINTS_DATA", 10, ...);
// Subscribe to joint state feedback
imu_data_sub_ = node_->create_subscription<drdds::msg::ImuData>("/IMU_DATA", 10, ...);
// Subscribe to IMU data
health_data_sub_ = node_->create_subscription<drdds::msg::BatteryData>("/BATTERY_DATA", 10, ...);
// Subscribe to battery data

SetJointCommand maps the input matrix to drdds::msg::JointsDataCmd:

msg.data.joints_data[i].position = (input(i, 1) - joint_config_[i].offset) * joint_config_[i].dir;
// Target position (with offset and direction mapping)
msg.data.joints_data[i].velocity = input(i, 3) * joint_dir_[i];
// Target velocity
msg.data.joints_data[i].torque = input(i, 4) * joint_dir_[i];
// Feedforward torque
msg.data.joints_data[i].kp = input(i, 0);
// Position stiffness gain
msg.data.joints_data[i].kd = input(i, 2);
// Velocity damping gain
msg.data.joints_data[i].control_word = kIndexMotorControl;
// Control word
void Handler(const drdds::msg::JointsData::SharedPtr msg) // Joint data callback
void HandlerIMU(const drdds::msg::ImuData::SharedPtr msg) // IMU data callback
void HandlerHealth(const drdds::msg::BatteryData::SharedPtr msg) // Battery data callback

Lite3Interface inherits DdsInterface, is a 12 DOF quadruped robot, and does not perform offset and direction conversion on joint data.

Lite3Interface(const std::string &robot_name) : DdsInterface(robot_name, 12) {
...
}

Lite3Interface’s SetJointCommand uses input values directly without offset and direction mapping:

virtual void SetJointCommand(Eigen::Matrix<float, Eigen::Dynamic, 5> input) {
for (int i = 0; i < dof_num_; ++i) {
msg.data.joints_data[i].position = input(i, 1);
msg.data.joints_data[i].velocity = input(i, 3);
msg.data.joints_data[i].torque = input(i, 4);
msg.data.joints_data[i].kp = input(i, 0);
msg.data.joints_data[i].kd = input(i, 2);
msg.data.joints_data[i].control_word = kIndexMotorControl;
}
}

Handler also reads raw values directly without offset and direction mapping:

virtual void Handler(const drdds::msg::JointsData::SharedPtr msg) override {
for (int i = 0; i < dof_num_; ++i) {
joint_pos_(i) = msg->data.joints_data[i].position;
joint_vel_(i) = msg->data.joints_data[i].velocity;
joint_tau_(i) = msg->data.joints_data[i].torque;
}
}

Main topics:

  • /JOINTS_CMD — Joint control commands
  • /JOINTS_DATA — Joint state feedback
  • /IMU_DATA — IMU data
  • /BATTERY_DATA — Battery data (not yet available)
  • /GAMEPAD_DATA — Retroid gamepad data
  • /EMERGENCY_STOP_SIGNAL — Cross-process emergency stop signal

The current code directly uses message types from drdds:

  • drdds/msg/JointsData
  • drdds/msg/JointsDataCmd
  • drdds/msg/ImuData
  • drdds/msg/BatteryData
  • drdds/msg/GamepadData
  • drdds/msg/StdMsgInt32

Keyboard control mode simulation data flow:

graph LR
A["/rl_deploy"] -->|/JOINTS_CMD| B["/mujoco_simulation(Sim) or /lite3(Real)"]
B -->|/IMU_DATA| A
B -->|/JOINTS_DATA| A

Gamepad control mode real robot data flow:

graph LR
A["/rl_deploy"] -->|/JOINTS_CMD| B["/lite3"]
B -->|/IMU_DATA| A
B -->|/JOINTS_DATA| A
C["/retroid_gamepad"] -->|/GAMEPAD_DATA| A

lite3_transfer provides the following ROS2 services:

  • /SDK_MODE: Set publish frequency or exit SDK mode (drdds/srv/StdSrvInt32)
  • /EMERGENCY_STOP: Trigger emergency stop (drdds/srv/StdSrvInt32)