Skip to content

User Input and Communication Interface

The DR02 Pro SDK provides multiple user input methods, including keyboard, gamepad, and velocity command topics, all handled uniformly by UserCommandInterface.

The DR02 Pro supports three developer modes. The SDK requires entering the corresponding mode via the gamepad before running:

Developer ModeControl Scope
High-Level Motion Control ModeSDK controls motion via high-level commands such as /MOTION_STATE, /GAIT, /STEER
Full-Body Joint Control ModeSDK directly controls all 31 joints via /JOINTS_CMD
Upper-Body Joint Control ModeSDK controls waist and dual arms via /JOINTS_CMD; legs are controlled by the robot’s internal policy

Important: Only one publisher is allowed for /JOINTS_CMD at a time. Do not run other joint command publishers while the state machine is running.

The user command interface UserCommandInterface uniformly handles multiple input sources:

  • Subscribe to /GAMEPAD_KEY to receive gamepad button events
  • Subscribe to /STEER to receive normalized velocity commands
  • Subscribe to /REAL_STEER to receive actual velocity commands
  • Run KeyboardLoop in an independent thread for keyboard input handling
struct UserCommand {
double time_stamp; // Timestamp
int safe_control_mode; // Safety control mode (0=normal)
uint8_t target_mode; // Target motion state
float forward_vel_scale; // Forward velocity ratio
float side_vel_scale; // Lateral velocity ratio
float turning_vel_scale; // Rotational velocity ratio
};
KeyFunctionApplicable State
zEnter ZeroPosIdle
cEnter RLControlZeroPos
rEnter JointDampingAny
w/sForward / BackwardRLControl
a/dLeft / RightRLControl
q/eTurn Left / RightRLControl

Keyboard velocity commands are fixed normalized values of 0.70, and auto-return to zero approximately 320ms after key release.

ButtonFunction
L1Enter ZeroPos (only valid in Idle state)
L2Enter RLControl (only valid in ZeroPos state)
R2Enter JointDamping
Left StickForward / Left / Backward / Right
Right StickRotation

Gamepad button events are transmitted via the /GAMEPAD_KEY topic (string messages, e.g., G20_KEY_L1).

The state machine subscribes to two velocity command topics simultaneously:

TopicDescriptionInput Range
/STEERNormalized velocity command[-1.0, 1.0]
/REAL_STEERActual velocity commandAuto-normalized internally (x/1.0, y/0.75, yaw/2.25)
// Subscribe to gamepad button events
auto gamepad_sub = node->create_subscription<std_msgs::msg::String>(
"/GAMEPAD_KEY", 10,
[](const std_msgs::msg::String::SharedPtr msg) {
RCLCPP_INFO(node->get_logger(), "Gamepad key: %s", msg->data.c_str());
// Execute corresponding action based on button type
if (msg->data == "G20_KEY_L1") {
// L1 pressed, can trigger ZeroPos state
} else if (msg->data == "G20_KEY_L2") {
// L2 pressed, can trigger RLControl state
}
});
// Publish normalized velocity command
auto steer_pub = node->create_publisher<drdds::msg::Steer>(
"/STEER", 10);
// Construct velocity command
drdds::msg::Steer steer_cmd;
steer_cmd.x = 0.5f; // Forward 50% velocity
steer_cmd.y = 0.0f; // No lateral movement
steer_cmd.z = 0.0f; // No vertical movement
steer_cmd.roll = 0.0f; // No roll
steer_cmd.pitch = 0.0f; // No pitch
steer_cmd.yaw = 0.3f; // Right turn 30% angular velocity
// Publish command (recommended 20Hz frequency)
steer_pub->publish(steer_cmd);
// Publish actual velocity command (with units)
auto real_steer_pub = node->create_publisher<drdds::msg::Steer>(
"/REAL_STEER", 10);
drdds::msg::Steer real_cmd;
real_cmd.x = 0.5f; // Forward 0.5 m/s
real_cmd.y = 0.3f; // Left 0.3 m/s
real_cmd.yaw = 0.5f; // Rotation 0.5 rad/s
real_steer_pub->publish(real_cmd);

SafeController runs in an independent thread with a 2ms cycle, monitoring the following anomalies:

Detection ItemMethodTrigger Conditionsafe_control_mode
Joint Data AnomalyIsJointDataNormal()NaN values / Timeout 30ms / Data unchanged for 100 cycles3
Motor Over-TemperatureIsMotorTemperatureNormal()Temperature > 110°C2
IMU Data AnomalyIsImuDataNormal()NaN / Timeout 40ms4
union RobotErrorState {
struct {
uint32_t imu_num_error : 1; // IMU value anomaly
uint32_t imu_update_overtime : 1; // IMU update timeout
uint32_t motor_heat_warn : 1; // Motor over-temperature
uint32_t joint_num_error : 1; // Joint value anomaly
uint32_t joint_update_error : 1; // Joint update timeout
uint32_t reserved : 26;
};
uint32_t error_code;
};

Important: The DR02 Pro currently does not implement a cross-process emergency stop mechanism (e.g., /EMERGENCY_STOP_SIGNAL).

The DR02 Pro emergency stop relies only on the following methods:

  1. Gamepad Red Stop Button (Recommended)

    • In case of anomaly, press the red button on the gamepad to directly disconnect the control signal
    • The robot’s low-level controller enters a protective state upon receiving the signal
  2. safe_control_mode Safety Degradation

    • SafeController sets safe_control_mode != 0 when an anomaly is detected
    • Next cycle automatically switches to JointDamping state (full-body pure damping)
    • Returns to Idle state after 3 seconds
  3. Ctrl+C Soft Termination

    • Press Ctrl+C in the terminal to stop the SDK program
    • After state machine exit, /JOINTS_CMD is no longer published; the robot may fall due to loss of support
    • Only applicable in simulation environments or scenarios requiring immediate power-off

[!WARNING]

When operating the real robot, the gamepad red stop button should be the primary method for emergency stopping.