GR-Actuator
1. 概述
GR-Actuator 是 DDS 与 Fourier 机器人本体执行器之间的接口。它通过 DDS 接收本体关节命令,驱动腰部、头部和手臂执行器,并将本体关节状态和执行器故障通过 DDS 发布。
GR-W 本体没有双腿,本模块覆盖 21 个自由度:腰部 5 DOF、头部 2 DOF、双臂 14 DOF。请注意:左右灵巧手不属于 GR-Actuator。
| 元素 | 数值 |
|---|---|
| Domain ID | 123 |
| 周期 | 关节状态 1000 Hz 发布,本体控制循环约 1 ms |
| 硬件 | GR-W 本体关节执行器,共 21 DOF |
| Group 字段 | waist、head、left_manipulator、right_manipulator |
2. DDS 接口服务
2.1 Topics
订阅
| Topic | 消息类型 | 说明 |
|---|---|---|
robot_joint_cmd | JointGroupCmd | 本体控制组关节命令 |
发布
| Topic | 消息类型 | 频率 | 说明 |
|---|---|---|---|
robot_joint_state | RobotJointState | 1000 Hz | 当前本体关节状态(位置、速度、力矩) |
hal_actuator_error_code | ErrorCodes | 事件触发;持续故障最多约 10 Hz | 执行器故障码 |
服务
| Service | Request / Response | 说明 |
|---|---|---|
set_actuator_params | SetActuatorParams_Request / SetActuatorParams_Response | 设置控制组 PID 参数 |
set_actuator_behavior_enable | SetActuatorBehavior_Request / SetActuatorBehavior_Response | 使能或禁用控制组 |
2.2 IDL 定义
JointGroupCmd
Idl
struct PvatData7 {
double position[7]; // 目标位置,前 N 个自由度有效
double velocity[7]; // 目标速度
double acceleration[7]; // 目标加速度
double effort[7]; // 目标力矩或前馈力矩
};
struct JointGroupCmd {
HeaderPod header;
TracePointList trace_points;
ShortString group_names[6]; // 例如 "left_manipulator"
PvatData7 commands[6]; // 与 group_names 一一对应
};
GR-W 的 group_names 为 waist、head、left_manipulator、right_manipulator。各组分别包含 5、2、7、7 个自由度,commands[i] 只读取对应控制组实际自由度数量内的数据。
RobotJointState
Idl
struct RobotJointState {
HeaderPod header;
TracePointList trace_points;
double position[32]; // 当前关节位置
double velocity[32]; // 当前关节速度
double effort[32]; // 当前关节力矩
uint8 state_size;
};
GR-W 本体状态按整机关节顺序写入数组。消费端读取 21 个元素;灵巧手状态不在该消息内。
SetActuatorParams
Idl
enum ControlMode {
POSITION,
VELOCITY,
TORQUE,
PD
};
struct ControlParameters {
double pos_kp[7];
double pos_ki[7];
double pos_kd[7];
double pd_kp[7];
double pd_kd[7];
};
struct SetActuatorParams_Request {
HeaderPod header;
boolean force_reset; // 保留字段
ShortString group_name; // 目标控制组
ControlMode motor_mode; // POSITION 或 PD
ControlParameters params;
};
struct SetActuatorParams_Response {
HeaderPod header;
LongString message;
boolean success;
};
当前服务端支持 POSITION 和 PD 参数写入,结果以 success 为准。
SetActuatorBehavior
Idl
struct ControlBehavior {
boolean enable; // true 使能,false 禁用
uint8 motor_mode;
};
struct SetActuatorBehavior_Request {
HeaderPod header;
boolean force_reset; // 保留字段
ShortString group_name; // 目标控制组
ControlBehavior behavior;
};
struct SetActuatorBehavior_Response {
HeaderPod header;
LongString message;
boolean success;
};
当前公开服务为 set_actuator_behavior_enable,只使用 behavior.enable。
ErrorCodes
Idl
struct ErrorCode {
uint32 high32;
uint32 low32;
};
struct ErrorCodes {
std_msgs::msg::Header header;
uint8 source; // 1 = 执行器
sequence<ErrorCode> error_codes;
};
3. 基础示例
3.1 — 本体控制命令发布
Python
import time
from fourierdds_py import DDSInterface, PublisherQosProfile
import fourier_msgs_pod.msg.RobotJointCmd as RobotJointCmd
DOMAIN_ID = 123
GROUP_NAME = "left_manipulator"
DOF = 7
def short_string(value):
data = value.encode("utf-8")
if len(data) > 64:
raise ValueError("控制组名称超过 64 字节")
msg = RobotJointCmd.ShortString()
msg.content(data + b"\0" * (64 - len(data)))
return msg
dds = DDSInterface(domain_id=DOMAIN_ID)
pub = dds.create_publisher(
pub_sub_type=RobotJointCmd.JointGroupCmdPubSubType(),
topic_name="robot_joint_cmd",
qos_profile=PublisherQosProfile.best_effort(),
)
time.sleep(3)
msg = RobotJointCmd.JointGroupCmd()
msg.group_names([short_string(GROUP_NAME)] + [RobotJointCmd.ShortString() for _ in range(5)])
cmd = RobotJointCmd.PvatData__7()
for i in range(DOF):
cmd.position()[i] = 0.0
cmd.velocity()[i] = 0.0
cmd.acceleration()[i] = 0.0
cmd.effort()[i] = 0.0
msg.commands([cmd] + [RobotJointCmd.PvatData__7() for _ in range(5)])
pub.publish(msg)
3.2 — 本体关节状态订阅
Python
import time
from fourierdds_py import DDSInterface, SubscriberQosProfile
import fourier_msgs_pod.msg.RobotJointState as RobotJointState
dds = DDSInterface(domain_id=123)
def on_state(msg):
pos = msg.position()
vel = msg.velocity()
eff = msg.effort()
print(f"joint[0]: pos={pos[0]:.4f}, vel={vel[0]:.4f}, effort={eff[0]:.4f}")
dds.create_subscription(
pub_sub_type=RobotJointState.RobotJointStatePubSubType(),
topic_name="robot_joint_state",
callback=on_state,
qos_profile=SubscriberQosProfile.default(),
)
while True:
time.sleep(0.1)