Skip to content

The A2 Lite robot comes pre-installed with a motion control program, allowing users to directly control the robot’s movement by sending high-level linear and angular velocity commands. There is no need to develop low-level control models for walking and other functions. Additionally, the joints for the upper limbs and neck are open to direct HAL layer hardware interfaces.

By default, the low-level control interface for the lower limb joint motors is not open; only high-level speed commands can be used for overall control. If you need to develop your own motion control algorithms to replace the Agibot factory-installed algorithms, please contact the business or customer project manager to obtain the motion control development and deployment guide.

The Agibot motion control program is designed with a state machine that switches between different models and opens different upper limb control interfaces based on the current state. The state machine is shown in the following diagram:

Descriptions of each state are as follows:

Action TypeAction CodeChinese NameDetailed DescriptionCallable Interfaces
Safety ActionDEFAULTDefault ModeThe default action after the motion control starts.
Position Control ActionRL_JOINT_DEFAULTReinforced Standing ModeThe robot stands with reinforced position control, standing with straight legs.
Position Control ActionPASSIVE_UPPER_BODY_JOINT_SERVOLower Limb Passive, Upper Limb Servo ModeThe lower limbs are not enabled, and the arms can receive external joint servo commands.T2
Position Control ActionSIT_DOWNSitting ModeThe lower limbs perform the action, while the upper limbs remain stationary, coordinating with a chair to sit down.
Position Control ActionSTAND_UPStanding Up ModeThe lower limbs perform the action, while the upper limbs remain stationary, coordinating with a chair to stand up.
Force Control ActionRL_LOCOMOTION_DEFAULTReinforced Walking ModeA human-like walking mode trained through reinforcement learning, where the arms swing during walking.T1
Force Control ActionRL_LOCOMOTION_ARM_EXT_JOINT_SERVOReinforced Walking with Upper Limb Servo ModeThe lower limbs walk or stand in a human-like manner, while the upper limbs accept external joint servo commands, performing actions during walking or standing (using a full-body control reinforcement model for better stability).T1, T2
Force Control ActionRL_WHOLE_BODY_EXT_JOINT_SERVOFull-Body Action with Upper Limb Servo ModeSimilar to RL_LOCOMOTION_ARM_EXT_JOINT_SERVO, but with additional control over waist movements. The A2 robot does not have actual degrees of freedom in the waist, so waist movements are achieved through leg motor coordination.T1, T2, T3
Force Control ActionRL_WHOLE_BODY_DANCEFull-Body Dance ModeCan perform specified full-body dance actions.S1

It is generally not recommended to switch between non-force control states using the program. Only switching between force control states is recommended. Other state transitions, which involve lifting and lowering the robot, should be performed manually.### 7.1.2 State Machine Switching and Query RPC Interface

Interface Name pb:/aimdk.protocol.McActionService/SetAction
Function Overview Switch the motion control state machine
Interface Type HTTP JSON RPC
URL http://127.0.0.1:56322/rpc/aimdk.protocol.McActionService/SetAction
Input Parameters
{
  "header": {
    "timestamp": {
      "seconds": 1762800293,
      "nanos": 849579000,
      "ms_since_epoch": 1762800293849
    },
    "control_source": "ControlSource_SAFE"
  },
  "command": {
    "action": "McAction_USE_EXT_CMD",
    "ext_action": "RL_JOINT_DEFAULT"
  }
}
  • action: Fixed to McAction_USE_EXT_CMD
  • ext_action: The actual motion control action to switch to
Output Parameters
{
  "header": {
    "code": "0",
    "msg": "called successfully.",
    "timestamp": {
      "seconds": "1762829093",
      "nanos": 853246996,
      "ms_since_epoch": "0"
    },
    "trace_id": "",
    "domin": ""
  },
  "state": "CommonState_SUCCESS"
}
  • state: The status of the request call
Example Script examples/motion_control/SetAction.py
Notes
  • Asynchronous interface, completion of the call does not mean the switch is complete; use the GetAction interface to check if the switch is complete
  • This interface has no action restrictions
Interface Name pb:/aimdk.protocol.McActionService/GetAction
Function Overview Query the motion control state machine
Interface Type HTTP JSON RPC
URL http://127.0.0.1:56322/rpc/aimdk.protocol.McActionService/GetAction
Input Parameters
{}
Output Parameters
{
  "header": {
    "code": "0",
    "msg": "called successfully.",
    "timestamp": {
      "seconds": "1762828518",
      "nanos": 763620392,
      "ms_since_epoch": "0"
    },
    "trace_id": "",
    "domin": ""
  },
  "info": {
    "current_action": "McAction_DEFAULT",
    "ext_action": "",
    "status": "McActionStatus_RUNNING"
  }
}
  • current_action: The currently running action
  • ext_action: Extended action, generally not used
  • status: Action status, generally not used
Example Script example/mc/actions.py
Notes
  • This interface has no action restrictions

Generally, the above two interfaces are used together, as shown in the following code example:

def ensure_action(action_name: str, retries=3, retry_interval=1.0, mc_ip: str = "127.0.0.1"):
try:
for i in range(retries):
if get_action(mc_ip) == action_name:
return True
set_action(action_name, mc_ip)
time.sleep(0.1 if i == 0 else retry_interval)
except Exception as e:
print(f"Failed to set action: {e}")
return False
return False

7.1.3 Locomotion Control Command Topic Interface

Section titled “7.1.3 Locomotion Control Command Topic Interface”
Interface Name /motion/control/locomotion_velocity
Function Overview Locomotion control command
Interface Type ROS2 Topic
Input Parameters
{
  "data": {
    "mode": 0,
    "forward_velocity": 0.1,
    "lateral_velocity": 0.0,
    "angular_velocity": 0.0
  }
}
  • mode: Velocity control mode

    • 0 for remote control scenarios
    • 1 for navigation mode, with faster velocity response; 0.05 m/s activates stepping, and stepping stops after 500 ms without a velocity command
  • forward_velocity: Forward velocity, range -0.3-0.8 m/s

  • lateral_velocity: Lateral velocity, range -0.25-0.25 m/s

  • angular_velocity: Angular velocity, range -0.5-0.5 rad/s

Example Script examples/motion_control/walk.py
Notes
  • The ROS2 message type is ros2_plugin_proto/msg/RosMsgWrapper, which requires sourcing prebuilt/ros2_plugin_proto_x86_64/share/ros2_plugin_proto/local_setup.bash before use.
  • The call code for this interface is T1, and commands work better under RL_LOCOMOTION_DEFAULT
### 7.1.4 Waist Control Instruction Topic Interface
Interface Name /motion/control/move_waist
Function Overview Waist control instruction
Interface Type ROS2 Topic
Input Parameters
{
  "data": {
    "x": 0.0,
    "y": 0.0,
    "z": -0.1,
    "roll": 0.0,
    "pitch": 0.0,
    "yaw": 0.0
  }
}
  • x: Invalid field

  • y: Invalid field

  • z: Squat, range -0.25 to 0.00 m

  • roll: Invalid field

  • pitch: Bend forward, range 0 to 0.5236 rad, note the coupling relationship with z squat

    • As z increases, the maximum bend (pitch maximum value) linearly increases from 0 to 0.5236, then remains at the maximum value of 0.5236, and finally linearly decreases to 0.436
    • The three segments of z ranges are [0, -0.08], [-0.08, -0.17], [-0.17, -0.25]
    • The minimum pitch value is 0, it can only lean forward, not backward
  • yaw: Turn, range -0.5236 to 0.5236 rad

Example Script examples/motion_control/move_waist.py
Notes
  • The ROS2 type of this message is ros2_plugin_proto/msg/RosMsgWrapper, which requires sourcing prebuilt/ros2_plugin_proto_x86_64/share/ros2_plugin_proto/local_setup.bash before use
  • The call code for this interface is T3, and it can only be called in RL_WHOLE_BODY_EXT_JOINT_SERVO mode
  • The A2 robot does not have an independent waist degree of freedom in its physical design; this waist degree of freedom is a virtual one, simulated by reinforcement learning algorithms through leg joint motors

7.1.5 Neck Control Instruction and State Topic Interfaces

Section titled “7.1.5 Neck Control Instruction and State Topic Interfaces”
Interface Name /motion/control/neck_joint_command
Function Overview Neck control instruction
Interface Type ROS2 Topic
Input Parameters sensor_msgs::msg::JointState
  • name: Joint name, fixed as ["idx27_head_joint1", "idx28_head_joint2"], the second one is invalid but needs to be filled
  • position: Joint angle, the first value represents the head shaking degree of freedom, range -0.785 to 0.785 rad, the second value is invalid but needs to be filled
  • velocity: Invalid field, leave blank
  • effort: Invalid field, leave blank
Example Script examples/motion_control/neck.py
Notes
  • The call code for this interface is T2, and it can only be called in modes with JOINT_SERVO suffix
  • Note that in JOINT_SERVO mode, this interface is taken over by the motion_player module by default. Please disable it using examples/motion_player/disable_motion_player before sending instructions
Interface Name /motion/control/neck_joint_state
Function Overview Neck state topic
Interface Type ROS2 Topic
Output Parameters sensor_msgs::msg::JointState
  • position: Joint angle, the first value represents head shaking, other values are meaningless
Example Script examples/motion_control/joint_state.py
Notes
  • This interface has no Action restrictions
### 7.1.6 Neck Control Instructions and Status RPC Interface

The above neck control topic interface is suitable for scenarios requiring continuous and precise control of the neck angle, such as remote operation, and can only be called in JOINT_SERVO mode. For certain scenarios where simple control to a specific angle is needed, the following RPC interface can be used.

Interface Name pb:/aimdk.protocol.McMotionService/SetNeckCommand
Function Overview Set neck command
Interface Type HTTP JSON RPC
URL http://127.0.0.1:56322/rpc/aimdk.protocol.McMotionService/SetNeckCommand
Input Parameters
{
  "data": {
    "shake": {
      "name": "idx27_head_joint1",
      "position": 0.5,
      "velocity": 0.0,
      "effort": 0.0
    },
    "nod": {
      "name": "idx28_head_joint2",
      "position": 0.0,
      "velocity": 0.0,
      "effort": 0.0
    }
  }
}
  • Only the position field in the shake section is meaningful; the other fields should remain unchanged. The range is -0.785 to 0.785 rad.
  • The nod-related content is not meaningful and should be filled out as is.
Output Parameters
{
  "header": {
    "code": "0",
    "msg": "called successfully.",
    "timestamp": {
      "seconds": "1762845079",
      "nanos": 921954699,
      "ms_since_epoch": "0"
    },
    "trace_id": "",
    "domin": ""
  },
  "state": "CommonState_SUCCESS"
}
  • state: Call request status
Example Script examples/motion_control/SetNeckCommand.py
Notes
  • This interface has no Action restrictions.
  • Note that in JOINT_SERVO mode, this interface is taken over by the motion_player module by default. Please disable it using examples/motion_player/disable_motion_player before sending commands.
Interface Name pb:/aimdk.protocol.McMotionService/GetNeckState
Function Overview Get neck state
Interface Type HTTP JSON RPC
URL http://127.0.0.1:56322/rpc/aimdk.protocol.McMotionService/GetNeckState
Input Parameters
{}
Output Parameters
{
  "header": {
    "code": "0",
    "msg": "called successfully.",
    "timestamp": {
      "seconds": "1762846182",
      "nanos": 679221245,
      "ms_since_epoch": "0"
    },
    "trace_id": "",
    "domin": ""
  },
  "data": {
    "shake": {
      "name": "",
      "sequence": 0,
      "position": 0,
      "velocity": 0,
      "effort": 0
    },
    "nod": {
      "name": "",
      "sequence": 0,
      "position": 0,
      "velocity": 0,
      "effort": 0
    }
  }
}
  • state: Call request status
  • Only the position field in the shake section is meaningful, with a range of -0.785 to 0.785 rad. The other fields can be ignored.
Example Script examples/motion_control/GetNeckState.py
Notes This interface has no Action restrictions.
### 7.1.7 Arm Control Command and Status Topic Interfaces
Interface Name /motion/control/arm_joint_command
Function Overview Arm joint control command
Interface Type ROS2 Topic
Input Parameters sensor_msgs::msg::JointState
  • name: Joint names, fixed to ["idx13_left_arm_joint1", "idx14_left_arm_joint2", "idx15_left_arm_joint3", "idx16_left_arm_joint4", "idx17_left_arm_joint5", "idx18_left_arm_joint6", "idx19_left_arm_joint7", "idx20_right_arm_joint1", "idx21_right_arm_joint2", "idx22_right_arm_joint3", "idx23_right_arm_joint4", "idx24_right_arm_joint5", "idx25_right_arm_joint6", "idx26_right_arm_joint7"], joints 6 and 7 of both arms are invalid but need to be filled as placeholders
  • position: Joint angles, must fill in the angle values for 14 joints, where joints 6 and 7 of both arms are invalid but need to be filled as placeholders
  • velocity: Invalid field, set to 0.0
  • effort: Invalid field, set to 0.0
Example Script examples/motion_control/arm.py
Notes
  • The call code for this interface is T2, and it can only be called in modes with the suffix JOINT_SERVO

  • Note that in JOINT_SERVO mode, this interface is taken over by the motion_player module by default. Please disable it using examples/motion_player/disable_motion_player before sending commands.

    • This interface is recommended to be called at a frequency of 100 Hz. When calling, ensure that the interval between adjacent commands does not exceed 0.03, ensuring that the speed does not exceed 3 rad/s and the maximum acceleration does not exceed 6.28 rad/s^2. The commands should be as smooth as possible; otherwise, there may be jitter. It is recommended to use at least a basic low-pass filter method: y(k) = (1 - a) * y(k - 1) + a * x(k).
  • Angle limits are as follows (in radians)

    • idx13_left_arm_joint1: -2.91 ~ 2.91
    • idx14_left_arm_joint2: -0.46 ~ 1.60
    • idx15_left_arm_joint3: -2.91 ~ 2.91
    • idx16_left_arm_joint4: -2.00 ~ -0.03
    • idx17_left_arm_joint5: -2.94 ~ 2.94
    • idx20_right_arm_joint1: -2.91 ~ 2.91
    • idx21_right_arm_joint2: -1.60 ~ 0.46
    • idx22_right_arm_joint3: -2.91 ~ 2.94
    • idx23_right_arm_joint4: 0.03 ~ 2.00
    • idx24_right_arm_joint5: -2.94 ~ 2.94
Interface Name /motion/control/arm_joint_state
Function Overview Arm joint state topic
Interface Type ROS2 Topic
Output Parameters sensor_msgs::msg::JointState
  • name: 14 joint names, where joints 6 and 7 of both arms are invalid
  • position: 14 joint angles, where joints 6 and 7 of both arms are invalid
  • velocity: 14 joint velocities, where joints 6 and 7 of both arms are invalid
  • effort: 14 joint torques, where joints 6 and 7 of both arms are invalid
Example Script examples/motion_control/joint_state.py
Notes This interface has no Action restrictions
### 7.1.8 Upper and Lower Limb Joint State RPC Interface
Interface Name pb:/aimdk.protocol.McDataService/GetJointState
Function Overview Retrieve the state of upper and lower limb joints
Interface Type HTTP JSON RPC
URL http://127.0.0.1:56322/rpc/aimdk.protocol.McMotionService/GetJointState
Input Parameters
{}
Output Parameters
{
  "states": [
    {
      "name": "idx01_left_hip_roll",
      "sequence": 0,
      "position": 0.006256103515625,
      "velocity": 0.0048847198486328125,
      "effort": -13.367523193359375
    },
    {
      "name": "idx02_left_hip_yaw",
      "sequence": 0,
      "position": 0.013275146484375,
      "velocity": 0.024419784545898438,
      "effort": -11.658126831054688
    },
    {
      "name": "idx03_left_hip_pitch",
      "sequence": 0,
      "position": -0.11947822570800781,
      "velocity": -0.0048847198486328125,
      "effort": 1.015869140625
    },
    {
      "name": "idx04_left_tarsus",
      "sequence": 0,
      "position": 0.28732776641845703,
      "velocity": -0.0048847198486328125,
      "effort": -10.862030029296875
    },
    {
      "name": "idx05_left_toe_pitch",
      "sequence": 0,
      "position": -0.17624187469482422,
      "velocity": 0,
      "effort": 3.44881189007971
    },
    {
      "name": "idx06_left_toe_roll",
      "sequence": 0,
      "position": -0.012819436684095006,
      "velocity": 0.009888242426560891,
      "effort": 2.4995190811765715
    },
    {
      "name": "idx07_right_hip_roll",
      "sequence": 0,
      "position": -0.009918212890625,
      "velocity": -0.014652252197265625,
      "effort": 14.119659423828125
    },
    {
      "name": "idx08_right_hip_yaw",
      "sequence": 0,
      "position": -0.011749267578125,
      "velocity": 0.024419784545898438,
      "effort": 14.25640869140625
    },
    {
      "name": "idx09_right_hip_pitch",
      "sequence": 0,
      "position": -0.12344551086425781,
      "velocity": -0.0048847198486328125,
      "effort": -7.423675537109375
    },
    {
      "name": "idx10_right_tarsus",
      "sequence": 0,
      "position": 0.30014514923095703,
      "velocity": -0.014652252197265625,
      "effort": -18.676422119140625
    },
    {
      "name": "idx11_right_toe_pitch",
      "sequence": 0,
      "position": -0.18814373016357422,
      "velocity": -0.004883766174316406,
      "effort": 4.751964842417327
    },
    {
      "name": "idx12_right_toe_roll",
      "sequence": 0,
      "position": 0.012819560417340213,
      "velocity": 0.01981031932552883,
      "effort": -0.06747343675733508
    },
    {
      "name": "idx13_left_arm_joint1",
      "sequence": 0,
      "position": -0.053559280931949615,
      "velocity": -5.885322389076464e-05,
      "effort": -1.253999948501587
    },
    {
      "name": "idx14_left_arm_joint2",
      "sequence": 0,
      "position": 1.3100006580352783,
      "velocity": -6.644718814641237e-05,
      "effort": -2.2799999713897705
    },
    {
      "name": "idx15_left_arm_joint3",
      "sequence": 0,
      "position": 0,
      "velocity": 0,
      "effort": 2.2660000324249268
    },
    {
      "name": "idx16_left_arm_joint4",
      "sequence": 0,
      "position": -0.03490660712122917,
      "velocity": -4.366529537946917e-05,
      "effort": 1.715999960899353
    },
    {
      "name": "idx17_left_arm_joint5",
      "sequence": 0,
      "position": 1.5707954168319702,
      "velocity": 0,
      "effort": 0.06880000233650208
    },
    {
      "name": "idx18_left_arm_joint6",
      "sequence": 0,
      "position": 0.75,
      "velocity": 0,
      "effort": 0
    },
    {
      "name": "idx19_left_arm_joint7",
      "sequence": 0,
      "position": 2.995796503389102e-08,
      "velocity": 0,
      "effort": 0
    },
    {
      "name": "idx20_right_arm_joint1",
      "sequence": 0,
      "position": 0.03456582874059677,
```json
      "velocity": 6.644718723691767e-06,
      "effort": 0.722000002861023
    },
    {
      "name": "idx21_right_arm_joint2",
      "sequence": 0,
      "position": -1.3099987506866455,
      "velocity": 0,
      "effort": 1.7100000381469727
    },
    {
      "name": "idx22_right_arm_joint3",
      "sequence": 0,
      "position": -9.492455319559667e-07,
      "velocity": 7.40411487640813e-05,
      "effort": 1.5839999914169312
    },
    {
      "name": "idx23_right_arm_joint4",
      "sequence": 0,
      "position": 0.08476477861404419,
      "velocity": -5.1259259635116905e-05,
      "effort": 0.7919999957084656
    },
    {
      "name": "idx24_right_arm_joint5",
      "sequence": 0,
      "position": 1.5707954168319702,
      "velocity": 0,
      "effort": -0.5504000186920166
    },
    {
      "name": "idx25_right_arm_joint6",
      "sequence": 0,
      "position": -0.75,
      "velocity": 0,
      "effort": 0
    },
    {
      "name": "idx26_right_arm_joint7",
      "sequence": 0,
      "position": 3.001038685424783e-08,
      "velocity": 0,
      "effort": 0
    }
  ]
}
```
  • The 6th and 7th joints of both arms are invalid values
Example Script examples/motion_control/GetJointState.py
Notes This interface has no Action restrictions
### 7.1.9 Full-Body Dance List Retrieval RPC Interface
Interface Name pb:/aimdk.protocol.McMotionService/GetDanceTypeList
Function Overview Retrieve the list of supported full-body dances
Interface Type HTTP JSON RPC
URL http://127.0.0.1:56322/rpc/aimdk.protocol.McMotionService/GetDanceTypeList
Input Parameters
{}
Output Parameters
{
  "dance_name": [
    "Swing Dance",
    "Victory Dance"
  ],
  "dance_model_path": [
    "/home/agi/a2_simulation/motion_control_lite_1.2.22/bin/../config/motion_control/configuration/robot/raise_a2_lite/learning_controller_dance/models/policy_ybw_1127.onnx",
    "/home/agi/a2_simulation/motion_control_lite_1.2.22/bin/../config/motion_control/configuration/robot/raise_a2_lite/learning_controller_dance/models/policy_vict_1203.onnx"
  ],
  "dance_data_path": [
    "/home/agi/a2_simulation/motion_control_lite_1.2.22/bin/../config/motion_control/configuration/robot/raise_a2_lite/learning_controller_dance/models/export_data_ybw.npy",
    "/home/agi/a2_simulation/motion_control_lite_1.2.22/bin/../config/motion_control/configuration/robot/raise_a2_lite/learning_controller_dance/models/export_data_vict_v6.npy"
  ],
  "dance_time": [
    93.64,
    75.56
  ]
}
  • dance_name: Dance name, used for input to the play interface
  • dance_model_path: Location of the dance model file, no need to pay attention
  • dance_data_path: Location of the dance data file, no need to pay attention
  • dance_time: Duration of the dance in seconds
Example Script examples/motion_control/GetDanceTypeList.py
Notes
  • This interface has no call restrictions

7.1.10 Full-Body Dance Playback RPC Interface

Section titled “7.1.10 Full-Body Dance Playback RPC Interface”
Interface Name pb:/aimdk.protocol.McMotionService/SelectDanceType
Function Overview Full-body dance playback
Interface Type HTTP JSON RPC
URL http://127.0.0.1:56322/rpc/aimdk.protocol.McMotionService/SelectDanceType
Input Parameters
{
  "header": {
    "timestamp": {
      "seconds": 1762818960,
      "nanos": 172949000,
      "ms_since_epoch": 1762818960172
    },
    "control_source": "ControlSource_SAFE"
  },
  "dance_name": "jiangnan"
}
  • dance_name: Dance name, which needs to be obtained from the above dance list retrieval interface
Output Parameters
{
  "header": {
    "code": "0",
    "msg": "",
    "timestamp": {
      "seconds": "1762847760",
      "nanos": 178468357,
      "ms_since_epoch": "0"
    },
    "trace_id": "",
    "domin": ""
  },
  "state": "CommonState_SUCCESS"
}
  • state: Call request status
Example Script examples/motion_control/SelectDanceType.py
Notes
  • The call code for this interface is S1, and it can only be called in RL_WHOLE_BODY_DANCE mode