A3-Ultra 机器人出厂预搭载了运动控制程序,用户只需发送高层指令即可直接控制机器人行走,无需开发行走等功能的底层控制模型。
智元运控程序内部设计了状态机,在不同状态下会切换不同的模型。状态机如下图所示:

对于各个状态说明如下:
| Action 类型 |
Action 代码 |
中文名称 |
详细说明 |
可调用的控制接口 |
| 安全 Action |
PASSIVE |
默认模式 |
运控启动之后的默认 action |
|
| 安全 Action |
DAMPING |
阻尼模式 |
关节也可以认为移动,但是高阻尼,可固定 |
|
| 位控 Action |
PD_STAND |
位控站立模式 |
机器人位控站立,进入力控模式前关节初始化 |
|
| 力控 Action |
MOTION |
运动模式 |
该模式下可以行走,做上肢动作,跳舞等 |
- /motion/control/arm_joint_command
|
| 力控 Action |
SIT_DOWN |
坐下模式 |
与STAND_UP模式联用 |
|
| 力控 Action |
STAND_UP |
站起模式 |
与SIT_DOWN模式联用 |
|
| 力控 Action |
LIE_DOWN |
躺下模式 |
与GET_UP模式联用 |
|
| 力控 Action |
GET_UP |
起身模式 |
与LIE_DOWN模式联用 |
|
| 力控 Action |
PACKAGE_LIE_DOWN |
包装箱趟入模式 |
与PACKAGE_GET_UP模式联用 |
|
| 力控 Action |
PACKAGE_GET_UP |
包装箱起身模式 |
与PACKAGE_LIE_DOWN模式联用 |
|
一般情况下不推荐使用程序进行力控之外的切换,仅推荐程序在各个力控状态下切换,其余切换因涉及机器人吊起放下等操作仅可手动操作。
控制类接口一般有 Action 要求,未注明 Action 要求的接口以及查询类接口一般无 Action 限制。
机器人除行走控制命令外,其余关节控制topic接口默认情况下均被motion_player模块占用,下发关节控制命令前需关闭motion_player模块。命令如下:
curl -i \ -H 'content-type:application/json' \ -X POST 'http://127.0.0.1:50080/json/stop_app' \ -d '{"app_name": "motion_ player"}'
curl -i \ -H 'content-type:application/json' \ -X POST 'http://127.0.0.1:50080/json/start_app' \ -d '{"app_name": "motion_ player"}'
注意关闭motion_player模块后无法播放资源管理模块中的动作内容
| 接口名 |
pb:/aimdk.protocol.MotionControlActionService/SetAction |
| 功能概述 |
切换运动控制状态机 |
| 接口类型 |
HTTP JSON RPC |
| URL |
http://10.42.10.12:56322/rpc/aimdk.protocol.MotionControlActionService/SetAction |
| 入参 |
{
"header": {
"timestamp": {
"seconds": 1763614279,
"nanos": 847810000,
"ms_since_epoch": 1763614279847
},
"control_source": "ControlSource_SAFE"
},
"command": {
"action": "MotionControlAction_GET_UP",
"ext_action": "GET_UP"
}
}
- action: 从GetAvailableActions接口获取
- ext_action: 从GetAvailableActions接口获取
|
| 出参 |
{
"header": {
"code": "0",
"msg": "called successfully.",
"timestamp": {
"seconds": "1763643079",
"nanos": 849593506,
"ms_since_epoch": "0"
},
"trace_id": "",
"domin": ""
},
"state": "CommonState_SUCCESS"
}
|
| 示例脚本 |
examples/mc/S_SetAction.py |
| 备注 |
- 异步接口,调用完成不代表切换即完成,需配合 GetAction 接口查询切换是否完成
- 本接口无 Action 限制
|
| 接口名 |
pb:/aimdk.protocol.MotionControlActionService/GetAction |
| 功能概述 |
查询运动控制状态机 |
| 接口类型 |
HTTP JSON RPC |
| URL |
http://10.42.10.12:56322/rpc/aimdk.protocol.MotionControlActionService/GetAction |
| 入参 |
{}
|
| 出参 |
{
"header": {
"code": "0",
"msg": "called successfully.",
"timestamp": {
"seconds": "1763643026",
"nanos": 8207141,
"ms_since_epoch": "0"
},
"trace_id": "",
"domin": ""
},
"info": {
"current_action": "MotionControlAction_PASSIVE",
"ext_action": "",
"status": "MotionControlActionStatus_RUNNING"
}
}
- current_action: 当前运行的 Action
- ext_action: 扩展 Action,一般不使用
- status:Action 状态,一般不使用
|
| 示例脚本 |
example/mc/S_GetAction.py |
| 备注 |
|
| 接口名 |
pb:/aimdk.protocol.MotionControlActionService/GetAvailableActions |
| 功能概述 |
获取可用动作 |
| 接口类型 |
HTTP JSON RPC |
| URL |
http://10.42.10.12:56322/rpc/aimdk.protocol.MotionControlActionService/GetAvailableActions |
| 入参 |
{
"header": {
"timestamp": {
"seconds": "0",
"nanos": 0,
"ms_since_epoch": "1744598548952"
}
}
}
|
出参
|
{
"header": {
"code": "0",
"msg": "called successfully.",
"timestamp": {
"seconds": "1775639638",
"nanos": 585833612,
"ms_since_epoch": "0"
},
"trace_id": "module_mc",
"domin": ""
},
"commands": [
{
"action": "MotionControlAction_DAMPING",
"ext_action": "DAMPING"
},
{
"action": "MotionControlAction_GET_UP",
"ext_action": "GET_UP"
},
{
"action": "MotionControlAction_LIE_DOWN",
"ext_action": "LIE_DOWN"
},
......
]
}
- action:可切换的action名称,
- ext_action:action代码名,与action出参对应
|
| 示例脚本 |
examples/mc/S_SetAction.py |
| 备注 |
一般会通过GetAvailableActions接口查询当前可切换action状态,再通过SetAction接口设置action状态 |
| 接口名 |
/motion/control/locomotion_velocity |
| 功能概述 |
行走控制指令 |
| 接口类型 |
ROS2 Topic |
| 入参 |
{
"data": {
"mode": MotionControl_LocomotionMode_DEFAULT,
"forward_velocity": 0.1,
"lateral_velocity": 0.0,
"angular_velocity": 0.0
}
}
-
mode: 速度控制模式
- MotionControl_LocomotionMode_DEFAULT为默认模式
- MotionControl_LocomotionMode_NAVIGATION为导航模式
-
forward_velocity: 前进速度比例系数,发送比例系数范围-1.0~1.0 ,+为前进,-为后退,由mc计算速度
-
lateral_velocity: 水平速度比例系数,发送比例系数范围-1.0~1.0 ,+为左侧移动,-为右侧移动,由mc计算速度
-
angular_velocity: 旋转速度比例系数,发送比例系数范围-1.0~1.0 ,+为左旋转,-为右旋转,由mc计算速度
|
| 示例脚本 |
examples/mc/walk.py |
| 备注 |
|
| 接口名 |
/motion/control/arm_joint_command |
| 功能概述 |
手臂关节控制指令 |
| 接口类型 |
ROS2 Topic |
| 入参 |
sensor_msgs::msg::JointState
- name:关节名称,固定填写为["left_shoulder_pitch_joint","left_shoulder_roll_joint","left_shoulder_yaw_joint",
"left_elbow_joint",
"left_wrist_roll_joint",
"left_wrist_pitch_joint",
"left_wrist_yaw_joint",
"right_shoulder_pitch_joint",
"right_shoulder_roll_joint",
"right_shoulder_yaw_joint",
"right_elbow_joint",
"right_wrist_roll_joint",
"right_wrist_pitch_joint",
"right_wrist_yaw_joint"]
- position:关节角度,必须填写 14 个关节的角度值
- velocity: 无效字段,置为 0.0 即可
- effort: 无效字段,置为 0.0 即可
|
| 示例脚本 |
examples/mc/arm.py |
| 备注 |
-
本接口推荐以 100 Hz 的频率进行调用,调用时需要注意相邻指令间隔不要超过 30ms,确保速度不超过 4 rad/s,并且指令尽量顺滑,否则可能会有抖动,推荐起码使用基本的低通滤波方法:y(k) = (1 - a) * y(k - 1) + a * x(k)。
-
角度限位如下(单位 rad)
- left_shoulder_pitch_joint: ±2.967
- left_shoulder_roll_joint: ±1.588
- left_shoulder_yaw_joint: ±2.793
- left_elbow_joint: -1.047 ~ 2.444
- left_wrist_roll_joint: ±0.576
- left_wrist_pitch_joint: ±1.623
- left_wrist_yaw_joint: ±2.793
- right_shoulder_pitch_joint: ±2.967
- right_shoulder_roll_joint: ±1.588
- right_shoulder_yaw_joint: ±2.793
- right_elbow_joint: -1.047 ~ 2.444
- right_wrist_roll_joint: ±0.576
- right_wrist_pitch_joint: ±1.623
- right_wrist_yaw_joint: ±2.793
-
本接口有调用限制,仅可在 MOTION 状态下调用
-
由于motion_player模块一直在向motion_control模块下发命令,在下发命令前请关闭motion_player模块
|
| 接口名 |
/motion/control/arm_joint_state |
| 功能概述 |
手臂关节状态话题 |
| 接口类型 |
ROS2 Topic |
| 出参 |
sensor_msgs::msg::JointState
- name: 14 个关节名称
- position: 14 个关节角度
- velocity: 14 个关节速度
- effort: 14 个关节力矩
|
| 示例脚本 |
examples/mc/joint_state.py |
| 备注 |
本接口无 Action 限制 |
| 接口名 |
/motion/control/move_waist |
| 功能概述 |
腰部姿态控制 |
| 接口类型 |
ros2 topic |
| 入参 |
{
"header": {
"timestamp": {
"seconds": 1763681490,
"nanos": 943287000,
"ms_since_epoch": 1763681490943
},
"control_source": "ControlSource_MANUAL"
},
"waist_pitch": 0.1,
"waist_roll": 0,
"waist_yaw": 0,
"waist_height": -0.1,
}
double waist_pitch // range: [-0.5, 0.5] 单位:弧度 double waist_roll // range: [-0.3, 0.3] 单位:弧度 double waist_yaw // range: [-1.57, 1.57] 单位:弧度 double waist_height // range: [-0.4, 0.0] 单位:米 |
| 示例脚本 |
examples/mc/move_waist.py |
| 备注 |
|
| 接口名 |
/motion/control/neck_joint_command |
| 功能概述 |
脖子控制指令 |
| 接口类型 |
ROS2 Topic |
| 入参 |
sensor_msgs::msg::JointState
- name:关节名称,固定填写为 ["head_yaw_joint", "head_pitch_joint"]
- position:关节角度,第一个值代表摇头自由度,范围 -0.9 到 0.9,第二个值代表点头自由度,范围 -0.3 到 0.3
- velocity: 无效字段,不填
- effort: 无效字段,不填
|
| 示例脚本 |
examples/mc/neck.py |
| 备注 |
|
| 接口名 |
/motion/control/neck_joint_state |
| 功能概述 |
脖子状态话题 |
| 接口类型 |
ROS2 Topic |
| 出参 |
sensor_msgs::msg::JointState
- position:关节角度,第一个值代表摇头自由度,范围 -0.9 到 0.9,第二个值代表点头自由度,范围 -0.3 到 0.3
|
| 示例脚本 |
examples/mc/joint_state.py |
| 备注 |
|
| 接口名 |
/motion/control/hand_joint_command |
| 功能概述 |
手指控制指令 |
| 接口类型 |
ROS2 Topic |
| 入参 |
sensor_msgs::msg::JointState
- frame_id: A3 的手部类型。A3 支持 AgiHand 和 O10Hand 两种类型;不填写时默认 AgiHand。当前手部类型可通过 hand_joint_state 话题中 header.frame_id 字段识别
- name:关节名称,可不填,保持默认即可,或从hand_joint_state话题中的name字段获取
- position:关节角度,顺序与name字段关节对应,范围 0 到 2000,抽象值无单位,0 代表完全张开,2000 代表完全并拢
- velocity: 无效字段,不填
- effort: 关节力矩,顺序与name字段关节对应,手部为AgiHand时,范围 0 到 5700,0 代表对应推杆电机无力矩,5700 代表力矩达到最大 5.7N,手部为O10Hand时不填
|
| 示例脚本 |
examples/mc/hand.py |
| 备注 |
-
手指的控制逻辑是力矩和位置二者满足其一就会停止运动,例如针对某根手指传入 1000 的位置,5700 的力矩,如果没有外物卡住手指,当位置达到 1000 时,力矩不会继续加大,此时力矩会处于一个较小的值,如果外物卡住手指(抓住某物体等),力矩会持续加大到 5700 附近,对应电缸输出 5.7N 的力矩
-
本接口有调用限制,仅可在 motion 调用
-
由于motion_player模块一直在向motion_control模块下发命令,在下发命令前请关闭motion_player模块
|
| 接口名 |
/motion/control/hand_joint_state |
| 功能概述 |
手指状态话题 |
| 接口类型 |
ROS2 Topic |
| 出参 |
sensor_msgs::msg::JointState
- name:各个手指的关节名称
- frame_id:A2手部类型
- position:各个手指的关节角度,范围 0 到 2000
- velocity:无效字段
- effort:各个手指的力矩,范围 0 到 5700。
AgiHand的出参为12维对应每个关节,O10Hand出参由多维数组拼接。
包含双手的压力传感器阵列数据。数据排列如下:
- 左手压力: 16维 thumb + 16维 index + 16维 middle + 16维 ring + 16维 pinky + 25维 palm (掌心) + 25维 back_of_hand (手背)
- 右手压力:结构和顺序与左手相同,追加在左手数据之后
|
| 示例脚本 |
examples/mc/joint_state.py |
| 备注 |
- 位置因零位影响,可能范围略微有所漂移,为正常现象
- 力矩因手指内的连杆机构、转轴、以及弹簧等级机构都会带来一些影响,可能会出现略小于 0 的负值(-1000 以内),为正常现象
- 手指受外力影响时同样会出现负值,为正常现象
- 本接口无 Action 限制
|