7.1 Motion Control Section

7.1 Motion Control Section

7.1.1 Overall Introduction

The A2 robot comes pre-installed with motion control programs, 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 or other functions. Additionally, the upper limb and neck joint interfaces provide direct access to hardware interfaces at the HAL layer.

By default, the low-level control interface for the lower limb joint motors is not open; they can only be controlled through high-level speed commands. If you need to develop your own motion control algorithms to replace the Agibot factory-installed algorithms, please refer to the "A2 Ultra Low-Level Motion Control Development Guide" in the documentation. Please read the risk warnings and safety precautions for motion control development carefully before proceeding.

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 Control Interfaces
Safety ActionDEFAULTDefault ModeThe default action after the motion control starts
Position Control ActionRL_JOINT_DEFAULTReinforced Position Control Standing ModeThe robot stands with reinforced position control, straight legs
Position Control ActionPASSIVE_UPPER_BODY_JOINT_SERVOLower Limb Passive, Upper Limb Servo ModeLower limbs are not enabled, arms can receive external joint servo commands
  • /motion/control/arm_joint_command
  • /motion/control/neck_joint_command
  • /motion/control/hand_joint_command
Position Control ActionPASSIVE_UPPER_BODY_PLANNING_MOVELower Limb Passive, Upper Limb RRT Planning ModeLower limbs are not enabled, upper limb path planning, RPC receives target joint angles or SE3 positions
  • PlanningMove
Position Control ActionPASSIVE_UPPER_BODY_COLLISON_ESCAPELower Limb Passive, Upper Limb Collision Avoidance ModeLower limbs are not enabled, upper limb avoids self-collision, can be used when the planning interface cannot be called after a collision, switching to this action will automatically separate
Position Control ActionPASSIVE_UPPER_BODY_ONLINE_PLANNINGLower Limb Passive, Upper Limb NMPC Planning ModeLower limbs are not enabled, upper limb path planning, RPC receives target joint angles or SE3 positions, can interrupt the current target
  • PlanningMove
Position Control ActionSIT_DOWNPosition Control Sitting ModeLower limb action, upper limbs remain still, works with a chair to sit down
Position Control ActionSTAND_UPPosition Control Standing Up ModeLower limb action, upper limbs remain still, works with a chair to stand up
Position Control ActionMOBILE_PLATFORM_STAND_UPMobile Platform Position Control Standing Up ModeLower limb action, upper limbs remain still
Position Control ActionMOBILE_PLATFORM_SIT_DOWNMobile Platform Position Control Sitting Down ModeLower limb action, upper limbs remain still
Position Control ActionRL_SIT_DOWN_PASSIVE_POWER_OFFReinforced Deep Sit and Lean Back ModeLower limb action, upper limbs remain still, experimental feature, not recommended for use
Position Control ActionRL_STAND_UP_PREP_POWER_OFFReinforced Deep Sit and Stand Up Preparation ModeLower limb action, upper limbs remain still, experimental feature, not recommended for use
Force Control ActionRL_LOCOMOTION_DEFAULTReinforced Walking ModeHuman-like walking mode trained with reinforcement learning, arms swing while walking
  • /motion/control/locomotion_velocity
Force Control ActionRL_LOCOMOTION_ARM_EXT_JOINT_SERVOReinforced Walking with Upper Limb Servo ModeLower limbs walk or stand in a human-like manner, upper limbs accept external joint servo commands, perform actions while walking or standing (uses a full-body control reinforcement model, more stable)
  • /motion/control/locomotion_velocity
  • /motion/control/arm_joint_command
  • /motion/control/neck_joint_command
  • /motion/control/hand_joint_command
Force Control ActionRL_LOCOMOTION_ARM_EXT_PLANNING_MOVEReinforced Standing with Upper Limb RRT Planning ModeLower limbs stand with force control, upper limb path planning, RPC receives target joint angles or SE3 positions
  • /motion/control/locomotion_velocity
  • PlanningMove
Force Control ActionRL_LOCOMOTION_ARM_EXT_COLLISON_ESCAPEReinforced Standing with Upper Limb Collision Avoidance ModeLower limbs stand with force control, upper limb avoids self-collision, can be used when the planning interface cannot be called after a collision, switching to this action will automatically separate
  • /motion/control/locomotion_velocity
Force Control ActionRL_WHOLE_BODY_EXT_JOINT_SERVOWhole Body Action with Upper Limb Servo ModeLower limbs stand with force control, arms can receive external joint servo commands, additional waist control, the A2 robot does not have actual degrees of freedom in the waist, waist movements are achieved through leg motor coordination
  • /motion/control/locomotion_velocity
  • /motion/control/arm_joint_command
  • /motion/control/neck_joint_command
  • /motion/control/hand_joint_command
  • /motion/control/move_waist
  • /motion/control/move_waist_lift
  • /motion/control/move_waist_pitch
  • /motion/control/move_waist_twist
Force Control ActionRL_WHOLE_BODY_DANCEWhole Body Dance ModeCan run specified whole-body dance actions
  • SelectDanceType
  • GetDanceTypeList
Force Control ActionRL_WHOLE_BODY_EXT_ONLINE_PLANNINGReinforced Standing with Upper Limb NMPC Planning Mode
  • /motion/control/locomotion_velocity
  • /motion/control/move_waist
  • /motion/control/move_waist_lift
  • /motion/control/move_waist_pitch
  • /motion/control/move_waist_twist
  • PlanningMove

Generally, it is not recommended to use the program for switching other than force control. It is only recommended to switch between different force control states using the program. Other switches, which involve operations such as lifting and lowering the robot, should only be performed manually.

Control interfaces generally have Action requirements. Interfaces that do not specify Action requirements and query interfaces generally have no Action restrictions.

7.1.2 State Machine Switching and Querying RPC Interfaces

Interface Namepb:/aimdk.protocol.McActionService/SetAction
Function OverviewSwitch the motion control state machine
Interface TypeHTTP JSON RPC
URLhttp://192.168.100.100:56322/rpc/aimdk.protocol.McActionService/SetAction
Input Parameters
text
{
  "header": {
    "timestamp": {
      "seconds": 1763614279,
      "nanos": 847810000,
      "ms_since_epoch": 1763614279847
    },
    "control_source": "ControlSource_SAFE"
  },
  "command": {
    "action": "McAction_USE_EXT_CMD",
    "ext_action": "RL_LOCOMOTION_DEFAULT"
  }
}
  • action: Fixed to McAction_USE_EXT_CMD
  • ext_action: The actual motion control Action to switch to
Output Parameters
text
{
  "header": {
    "code": "0",
    "msg": "called successfully.",
    "timestamp": {
      "seconds": "1763643079",
      "nanos": 849593506,
      "ms_since_epoch": "0"
    },
    "trace_id": "",
    "domin": ""
  },
  "state": "CommonState_SUCCESS"
}
  • state: The status of the request call
Example Scriptexamples/mc/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 Namepb:/aimdk.protocol.McActionService/GetAction
Function OverviewQuery the motion control state machine
Interface TypeHTTP JSON RPC
URLhttp://192.168.100.100:56322/rpc/aimdk.protocol.McActionService/GetAction
Input Parameters
text
{}
Output Parameters
text
{
  "header": {
    "code": "0",
    "msg": "called successfully.",
    "timestamp": {
      "seconds": "1763643026",
      "nanos": 8207141,
      "ms_since_epoch": "0"
    },
    "trace_id": "",
    "domin": ""
  },
  "info": {
    "current_action": "McAction_RL_LOCOMOTION_ARM_EXT_JOINT_SERVO",
    "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 Scriptexample/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:

python
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 Walking Control Instruction Topic Interface

Interface Name/motion/control/locomotion_velocity
Function OverviewWalking control instruction
Interface TypeROS2 Topic
Input Parameters
text
{
  "data": {
    "mode": 0,
    "forward_velocity": 0.1,
    "lateral_velocity": 0.0,
    "angular_velocity": 0.0
  }
}
  • mode: Speed control mode
    • 0 for remote control scenarios
    • 1 for navigation mode, with faster speed response; 0.05 m/s activates stepping, and stepping stops if no speed command is received within 500ms after stepping
  • forward_velocity: Forward velocity, ranging from -0.3 to 1.2 m/s in RL_LOCOMOTION_DEFAULT mode, and from -0.4 to 0.6 m/s in other modes
  • lateral_velocity: Lateral velocity, ranging from -0.25 to 0.25 m/s in RL_LOCOMOTION_DEFAULT mode, and from -0.3 to 0.3 m/s in other modes
  • angular_velocity: Angular velocity, ranging from -1.0 to 1.0 rad/s in RL_LOCOMOTION_DEFAULT mode, and from -0.8 to 0.8 m/s in other modes
Example Scriptexamples/mc/walk.py
Notes
  • Due to joint heat dissipation limitations, continuous walking at speeds of 1.0 m/s or higher can cause motor overheating. Please avoid prolonged high-speed walking as much as possible. Closely monitor related warnings during high-speed walking, and stop the operation immediately if any motor abnormalities such as overheating occur.
  • The ROS2 type of this message is ros2_plugin_proto/msg/RosMsgWrapper. It requires sourcing prebuilt/ros2_plugin_proto_aarch64/share/ros2_plugin_proto/local_setup.bash before use.
  • This interface has call restrictions and can only be used in the following Actions. The commands work best in RL_LOCOMOTION_DEFAULT mode, while other modes have a smaller speed range.
    • RL_LOCOMOTION_DEFAULT
    • RL_LOCOMOTION_ARM_EXT_JOINT_SERVO
    • RL_LOCOMOTION_ARM_EXT_PLANNING_MOVE
    • RL_LOCOMOTION_ARM_EXT_COLLISION_ESCAPE
    • RL_WHOLE_BODY_EXT_ONLINE_PLANNING
    • RL_WHOLE_BODY_EXT_JOINT_SERVO

7.1.4 Waist Control Instruction and Status Topic Interface

Interface Name/motion/control/move_waist
Function OverviewWaist control instruction, can control all degrees of freedom simultaneously
Interface TypeROS2 Topic
Input Parameters
text
{
  "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, corresponding to three segments of z ranges [0, -0.08], [-0.08, -0.17], [-0.17, -0.25]
    • The minimum pitch value is 0, only able to lean forward, not backward
  • yaw: Turn, range -0.5236 to 0.5236 rad
Example Scriptexamples/mc/move_waist.py
Notes
  • The ROS2 message type for this is ros2_plugin_proto/msg/RosMsgWrapper, which requires sourcing prebuilt/ros2_plugin_proto_aarch64/share/ros2_plugin_proto/local_setup.bash before use
  • 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
  • This interface has usage restrictions and can only be called in the following Actions
    • RL_WHOLE_BODY_EXT_ONLINE_PLANNING
    • RL_WHOLE_BODY_EXT_JOINT_SERVO
Interface Name/motion/control/move_waist_lift
Function OverviewWaist squat control instruction
Interface TypeROS2 Topic
Input Parameters
text
{
  "header": {
    "timestamp": {
      "seconds": 1763681490,
      "nanos": 943287000,
      "ms_since_epoch": 1763681490943
    },
    "control_source": "ControlSource_MANUAL"
  },
  "waist_lift_value": 0.0
}
  • waist_lift_value: Waist squat, range -0.25 to 0.00 m
Example Scriptexamples/mc/move_waist_lift.py
Notes
  • The ROS2 message type for this is ros2_plugin_proto/msg/RosMsgWrapper, which requires sourcing prebuilt/ros2_plugin_proto_aarch64/share/ros2_plugin_proto/local_setup.bash before use
  • 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
  • This interface has usage restrictions and can only be called in the following Actions
    • RL_WHOLE_BODY_EXT_ONLINE_PLANNING
    • RL_WHOLE_BODY_EXT_JOINT_SERVO
Interface Name/motion/control/move_waist_twist
Function OverviewWaist twist (turn) control instruction
Interface TypeROS2 Topic
Input Parameters
text
{
  "header": {
    "timestamp": {
      "seconds": 1763681490,
      "nanos": 943287000,
      "ms_since_epoch": 1763681490943
    },
    "control_source": "ControlSource_MANUAL"
  },
  "waist_twist_value": 0.0
}
  • waist_twist_value: Twist angle, range -0.5236 to 0.5236 rad
Example Scriptexamples/mc/move_waist_twist.py
Notes
  • The ROS2 message type for this is ros2_plugin_proto/msg/RosMsgWrapper, which requires sourcing prebuilt/ros2_plugin_proto_aarch64/share/ros2_plugin_proto/local_setup.bash before use
  • 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
  • This interface has usage restrictions and can only be called in the following Actions
    • RL_WHOLE_BODY_EXT_ONLINE_PLANNING
    • RL_WHOLE_BODY_EXT_JOINT_SERVO
Interface Name/motion/control/move_waist_pitch
Function OverviewWaist bend forward instruction
Interface TypeROS2 Topic
Input Parameters
text
{
  "header": {
    "timestamp": {
      "seconds": 1763681490,
      "nanos": 943287000,
      "ms_since_epoch": 1763681490943
    },
    "control_source": "ControlSource_MANUAL"
  },
  "waist_pitch_value": 0.0
}
  • waist_pitch_value: Pitch angle, range 0 to 0.5236 rad, has a certain coupling relationship with squatting. For details, please refer to the /motion/control/move_waist interface documentation.
Example Scriptexamples/mc/move_waist_pitch.py
Notes
  • The ROS2 type of this message is ros2_plugin_proto/msg/RosMsgWrapper. It needs to be used after sourcing prebuilt/ros2_plugin_proto_aarch64/share/ros2_plugin_proto/local_setup.bash.
  • 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 the leg joint motors using a reinforcement learning algorithm.
  • This interface has call restrictions and can only be called in the following Actions:
    • RL_WHOLE_BODY_EXT_ONLINE_PLANNING
    • RL_WHOLE_BODY_EXT_JOINT_SERVO
Interface Name/motion/control/waist_state
Function OverviewWaist state topic
Interface TypeROS2 Topic
Output Parameters
text
{
  "x": 0.0,
  "y": 0.0,
  "z": 0.0,
  "roll": 0.0,
  "pitch": 0.0,
  "yaw": 0.0
}
  • The meaning of each field can be found in the documentation for the /motion/control/move_waist interface.
Example Scriptexamples/mc/waist_state.py
Notes
  • This interface has no Action restrictions.
  • The ROS2 type of this message is ros2_plugin_proto/msg/RosMsgWrapper. It needs to be used after sourcing prebuilt/ros2_plugin_proto_aarch64/share/ros2_plugin_proto/local_setup.bash.
  • The data field in RosMsgWrapper is serialized pb data of type McWaistValue. You need to install the protocol package using pip install prebuilt/a2_aimdk-1.3.0-py3-none-any.whl.

7.1.5 Neck Control Instructions and Status Topic Interface

Interface Name/motion/control/neck_joint_command
Function OverviewNeck control instructions
Interface TypeROS2 Topic
Input Parameterssensor_msgs::msg::JointState
  • name: Joint name, fixed to ["idx27_head_joint1", "idx28_head_joint2"]
  • position: Joint angle, the first value represents the yaw degree of freedom, ranging from -0.785 to 0.785 rad, the second value represents the pitch degree of freedom, ranging from -0.401 to 0.401 rad
  • velocity: Invalid field, leave blank
  • effort: Invalid field, leave blank
Example Scriptexamples/mc/neck.py
Notes
  • Note that in JOINT_SERVO mode, this interface is taken over by the motion_player module by default. Please call examples/motion_player/disable_motion_player.sh to disable it before sending instructions.
  • This interface has usage restrictions and can only be called in the following Actions:
    • RL_LOCOMOTION_ARM_EXT_JOINT_SERVO
    • RL_WHOLE_BODY_EXT_JOINT_SERVO
Interface Name/motion/control/neck_joint_state
Function OverviewNeck status topic
Interface TypeROS2 Topic
Output Parameterssensor_msgs::msg::JointState
  • position: Joint angle, the first value represents the yaw degree of freedom, ranging from -0.785 to 0.785 rad, the second value represents the pitch degree of freedom, ranging from -0.401 to 0.401 rad
Example Scriptexamples/mc/joint_state.py
Notes
  • This interface has no Action restrictions

7.1.6 Neck Control Instructions and Status RPC Interfaces

The above neck control topic interfaces are 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 sufficient, the following RPC interfaces can be used.

Interface Namepb:/aimdk.protocol.McMotionService/SetNeckCommand
Function OverviewSet neck command
Interface TypeHTTP JSON RPC
URLhttp://192.168.100.100:56322/rpc/aimdk.protocol.McMotionService/SetNeckCommand
Input Parameters
text
{
  "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 fields in shake and nod are meaningful; other fields should remain unchanged. The range for shake is -0.785 to 0.785 rad, and for nod, it is -0.401 to 0.401 rad.
Output Parameters
text
{
  "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 Scriptexamples/mc/SetNeckCommand.py
Notes
  • This interface has no Action restrictions.
  • Note that in JOINT_SERVO mode, this interface is by default taken over by the motion_player module. Please disable it using examples/motion_player/disable_motion_player.sh before sending commands.
Interface Namepb:/aimdk.protocol.McDataService/GetNeckState
Function OverviewGet neck state
Interface TypeHTTP JSON RPC
URLhttp://192.168.100.100:56322/rpc/aimdk.protocol.McMotionService/GetNeckState
Input Parameters
text
{}
Output Parameters
text
{
  "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
    }
  }
}
  • Only the position fields in shake and nod are meaningful; other fields should remain unchanged. The range for shake is -0.785 to 0.785 rad, and for nod, it is -0.401 to 0.401 rad.
Example Scriptexamples/mc/GetNeckState.py
NotesThis interface has no Action restrictions.

7.1.7 Finger Control Command and Status Topic Interface

Interface Name/motion/control/hand_joint_command
Function OverviewFinger control command
Interface TypeROS2 Topic
Input Parameterssensor_msgs::msg::JointState
  • frame_id: The hand type for A2. A2 supports two types: AgiHand and O10Hand; AgiHand is the default if not specified. The current hand type can be identified through the header.frame_id field in the hand_joint_state topic.
  • name:The joint name is optional; you can leave it blank and leave it as the default, or you can get it from the name field in the hand_joint_state topic.
  • position:Joint angles, in the order corresponding to the joints in the name field, range from 0 to 2000. The abstract value has no unit; 0 represents fully open, and 2000 represents fully closed.
  • velocity: Invalid field, leave blank
  • effort: Joint torque, the order corresponds to the joints in the name field. When the hand is AgiHand, the range is 0 to 5700, where 0 represents no torque in the corresponding actuator motor, and 5700 represents the maximum torque of 5.7N. When the hand is O10Hand, this field is left blank.
Example Scriptexamples/mc/hand.py
Notes
  • The finger control logic is such that the movement stops when either the position or torque condition is met. For example, if a position of 1000 and a torque of 5700 are sent for a specific finger, and there is no external object obstructing the finger, the movement will stop when the position reaches 1000, and the torque will remain at a lower value. If an external object obstructs the finger (e.g., grasping an object), the torque will increase to around 5700, corresponding to an output of 5.7N from the actuator.
  • Note that in JOINT_SERVO mode, this interface is by default taken over by the motion_player module. Please disable it using examples/motion_player/disable_motion_player.sh before sending commands.
  • This interface has usage restrictions and can only be called in the following Actions:
    • RL_LOCOMOTION_ARM_EXT_JOINT_SERVO
    • RL_WHOLE_BODY_EXT_JOINT_SERVO
Interface Name/motion/control/hand_joint_state
Function OverviewFinger status topic
Interface TypeROS2 Topic
Output Parameterssensor_msgs::msg::JointState
  • name: Names of the joints for each finger
  • frame_id:A2 Hand Type
  • position: Angles of the joints for each finger, range 0 to 2000
  • velocity: Invalid field
  • effort:The torque of each finger ranges from 0 to 5700.。
    AgiHand outputs 12-dimensional parameters corresponding to each joint, while O10Hand outputs are constructed from multi-dimensional arrays.
    This includes data from an array of pressure sensors on both hands. The data is arranged as follows:
    - Left hand pressure: 16-dimensional thumb + 16-dimensional index + 16-dimensional middle + 16-dimensional ring + 16-dimensional pinky + 25-dimensional palm + 25-dimensional back of hand
    - Right-hand pressure: The structure and sequence are the same as the left-hand pressure, appended after the left-hand pressure data.
Example Scriptexamples/mc/joint_state.py
Notes
  • Due to zero position influence, the position range may slightly drift, which is normal.
  • Torque may be slightly affected by the internal linkage, pivot, and spring mechanisms, and may show a small negative value (within -1000), which is normal.
  • Negative values may also appear when the fingers are subjected to external forces, which is normal.
  • This interface has no Action restrictions.

7.1.8 Finger Control Commands, Status RPC Interface

Interface Namepb:/aimdk.protocol.McMotionService/SetHandCommand
Function OverviewSet finger commands
Interface TypeHTTP JSON RPC
URLhttp://192.168.100.100:56322/rpc/aimdk.protocol.McMotionService/SetHandCommand
Input Parameters
text
{
  "data": {
    "left": {
      "agi_hand": {
        "finger": {
          "pos": {
            "thumb_pos_0": 0,
            "thumb_pos_1": 0,
            "index_pos": 0,
            "middle_pos": 1000,
            "ring_pos": 1000,
            "pinky_pos": 1000
          },
          "toq": {
            "thumb_toq_0": 100,
            "thumb_toq_1": 100,
            "index_toq": 100,
            "middle_toq": 100,
            "ring_toq": 100,
            "pinky_toq": 100
          }
        }
      }
    },
    "right": {
      "agi_hand": {
        "finger": {
          "pos": {
            "thumb_pos_0": 0,
            "thumb_pos_1": 1000,
            "index_pos": 1000,
            "middle_pos": 1000,
            "ring_pos": 1000,
            "pinky_pos": 1000
          },
          "toq": {
            "thumb_toq_0": 100,
            "thumb_toq_1": 100,
            "index_toq": 100,
            "middle_toq": 100,
            "ring_toq": 100,
            "pinky_toq": 100
          }
        }
      }
    }
  }
}
  • Position range: 0 to 2000, torque range: 0 to 5700
Output Parameters
text
{
  "header": {
    "code": "0",
    "msg": "called successfully.",
    "timestamp": {
      "seconds": "1763696261",
      "nanos": 18212539,
      "ms_since_epoch": "0"
    },
    "trace_id": "",
    "domin": ""
  },
  "state": "CommonState_SUCCESS"
}
  • state: Call request status
Example Scriptexamples/mc/SetHandCommand.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.sh before sending commands
Interface Namepb:/aimdk.protocol.McMotionService/GetHandState
Function OverviewGet finger state
Interface TypeHTTP JSON RPC
URLhttp://192.168.100.100:56322/rpc/aimdk.protocol.McDataService/GetHandState
Input Parameters
text
{}
Output Parameters
text
{
  "data": {
    "left": {
      "agi_hand": {
        "finger": {
          "pos": {
            "thumb_pos_0": 500,
            "thumb_pos_1": 1001,
            "index_pos": 998,
            "middle_pos": 998,
            "ring_pos": 999,
            "pinky_pos": 998
          },
          "toq": {
            "thumb_toq_0": 0,
            "thumb_toq_1": 0,
            "index_toq": 0,
            "middle_toq": 0,
            "ring_toq": 0,
            "pinky_toq": 0
          }
        }
      }
    },
    "right": {
      "agi_hand": {
        "finger": {
          "pos": {
            "thumb_pos_0": 500,
            "thumb_pos_1": 1000,
            "index_pos": 998,
            "middle_pos": 998,
            "ring_pos": 999,
            "pinky_pos": 998
          },
          "toq": {
            "thumb_toq_0": 0,
            "thumb_toq_1": 0,
            "index_toq": 0,
            "middle_toq": 0,
            "ring_toq": 0,
            "pinky_toq": 0
          }
        }
      }
    }
  }
}
  • The values represent the position and torque of the fingers, with a position range of 0 to 2000 and a torque range of 0 to 5700
Example Scriptexamples/mc/GetHandState.py
Notes
  • The position may slightly drift due to zero position influence, which is normal
  • The torque may be slightly less than 0 (within -1000) due to the internal linkage, shafts, and spring mechanisms in the fingers, which is normal
  • Negative values may also appear when the fingers are affected by external forces, which is normal
  • This interface has no Action restrictions

7.1.9 Arm Control Command and Status Topic Interfaces

Interface Name/motion/control/arm_joint_command
Function OverviewArm joint control command
Interface TypeROS2 Topic
Input Parameterssensor_msgs::msg::JointState
  • name: Joint names, fixed as ["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"]
  • position: Joint angles, must fill in the angle values for 14 joints
  • velocity: Invalid field, set to 0.0
  • effort: Invalid field, set to 0.0
Example Scriptexamples/mc/arm.py
Notes
  • Note that in JOINT_SERVO mode, this interface is taken over by the motion_player module by default. Please call examples/motion_player/disable_motion_player.sh to disable it 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 filtering 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
    • idx18_left_arm_joint6: -0.45 ~ 0.45
    • idx19_left_arm_joint7: -0.35 ~ 0.35
    • 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
    • idx25_right_arm_joint6: -0.45 ~ 0.45
    • idx26_right_arm_joint7: 0.35 ~ 0.35
  • This interface has usage restrictions and can only be called in the following Actions
    • PASSIVE_UPPER_BODY_JOINT_SERVO
    • RL_LOCOMOTION_ARM_EXT_JOINT_SERVO
    • RL_WHOLE_BODY_EXT_JOINT_SERVO
Interface Name/motion/control/arm_joint_state
Function OverviewArm joint state topic
Interface TypeROS2 Topic
Output Parameterssensor_msgs::msg::JointState
  • name: 14 joint names
  • position: 14 joint angles
  • velocity: 14 joint velocities
  • effort: 14 joint torques
The 6th and 7th joints of both arms are equivalent series joint data, with only the position field, and no velocity or effort fields
Example Scriptexamples/mc/joint_state.py
NotesThis interface has no Action restrictions

Note: The 6th and 7th joints of the dual-arm are connected via a parallel mechanism to control the wrist. Due to the geometric constraints of the parallel mechanism, the reachable workspace, when the translational degrees of freedom of the push rod are mapped to the pitch/roll serial degrees of freedom, does not form a rectangular area but rather a rhombus-like region, as illustrated by the blue area in the figure below:

For optimal tracking performance, the yellow region in the diagram is recommended. The corresponding joint limits for joints 6 and 7 are -0.3, 0.3 and -0.2, 0.2, respectively.

Below are the overall joint limit ranges for all joints of the dual-arm system after applying the aforementioned limits for the yellow region:

lower_bound: -3.0, -0.524, -2.967, -2.094, -2.967, -0.3, -0.2, -3.0, -1.5358897, -2.967, 0.1, -2.967, -0.3, -0.2

upper_bound: 3.0, 1.5358897, 2.967, -0.1, 2.967, 0.3, 0.2, 3.0, 0.524, 2.967, 2.094, 2.967, 0.3, 0.2

7.1.10 Arm Control Command RPC Interface

Interface Namepb:/aimdk.protocol.McMotionService/PlanningMove
Function OverviewUpper limb planning control interface
Interface TypeHTTP JSON RPC
URLhttp://192.168.100.100:56322/rpc/aimdk.protocol.McMotionService/PlanningMove
Input ParametersTwo types of input parameters can be passed, either the end-effector SE3 pose or joint angles
text
{
  "header": {
    "timestamp": {
      "seconds": 1763696866,
      "nanos": 231707000,
      "ms_since_epoch": 1763696866231
    },
    "control_source": "ControlSource_MANUAL"
  },
  "group": "McPlanningGroup_LEFT_ARM",
  "mode": "McPlanningMode_DEFAULT",
  "target": {
    "type": "SE3",
    "left": {
      "position": {
        "x": 0.35,
        "y": 0.35,
        "z": 0.25
      },
      "orientation": {
        "x": 0.570822,
        "y": -0.0606913,
        "z": -0.0106989,
        "w": 0.818758
      }
    },
    "right": {
      "position": {
        "x": 0.35,
        "y": -0.35,
        "z": 0.25
      },
      "orientation": {
        "x": -0.570817,
        "y": -0.0606912,
        "z": 0.0106992,
        "w": 0.818761
      }
    }
  },
  "reference": {
    "joint_position": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ]
  }
}
text
{
  "header": {
    "timestamp": {
      "seconds": 1763697224,
      "nanos": 63165000,
      "ms_since_epoch": 1763697224063
    },
    "control_source": "ControlSource_MANUAL"
  },
  "mode": "McPlanningMode_DEFAULT",
  "group": "McPlanningGroup_LEFT_ARM",
  "target": {
    "type": "JOINT",
    "joints": [
      0.142856,
      1.06998,
      -0.152017,
      -1.42857,
      2.3139,
      -0.100991,
      -0.269986
    ]
  }
}
  • group indicates the arm to be moved, McPlanningGroup_LEFT_ARM for the left arm, and McPlanningGroup_RIGHT_ARM for the right arm
  • target indicates the target point for the arm to move to,
    • position represents the target position
    • orientation represents the target quaternion
    • joints represent the joint angles to be passed in, sequentially from J1 to J7
  • reference's joint_position represents the reference joint angles, generally set to 0. If not all are 0 and the length is consistent with the number of robot arm joints, i.e., 7 reference values, the robot will try to reach the target point as close as possible to these joint angles
Output Parameters
text
{
  "header": {
    "code": "0",
    "msg": "called successfully.",
    "timestamp": {
      "seconds": "1763697146",
      "nanos": 154213397,
      "ms_since_epoch": "0"
    },
    "trace_id": "",
    "domin": ""
  },
  "task_id": "755481177558037",
  "state": "CommonState_PENDING"
}
  • Since this interface is asynchronous, it cannot directly return whether the task call is completed. You only need to save the task_id and then call the GetTaskState interface to query if the call is completed
Example Scriptsexamples/mc/PlanningMoveSE3.py examples/mc/PlanningMoveJoint.py
Notes
  • This interface has Action restrictions and can only be called in the following Actions:
    • PASSIVE_UPPER_BODY_PLANNING_MOVE
    • PASSIVE_UPPER_BODY_ONLINE_PLANNING
    • RL_LOCOMOTION_ARM_EXT_PLANNING_MOVE
    • RL_WHOLE_BODY_EXT_ONLINE_PLANNING
  • In ONLINE_PLANNING mode, the current executing target can be interrupted to execute the next target directly. In this mode, the task execution status cannot be queried because the execution judgment is handed over to a higher level.
  • In ONLINE_PLANNING mode, the difference between the command and the current position should not be too large. For example, moving the hand from in front of the body to behind the body may result in a failed plan, leaving the hand in an odd position.
  • The SE3 target point is represented in the base coordinate system of the robot, indicating the position and orientation of the robot's palm. There is a certain offset relative to the end link in the URDF to make the end link poses of the left and right arms consistent, facilitating calculations.
    • The left arm target point is offset by [-0.1, 0.0, 0.0] relative to left_arm_link07, and the quaternion orientation is offset by [0.0, 0.0, 0.70710678, 0.70710678]
    • The right arm target point is offset by [0.1, 0.0, 0.0] relative to right_arm_link07, and the quaternion orientation is offset by [-0.70710678, 0.70710678, 0.0, 1.0]
  • To calculate the palm's pose, you can first subscribe to the ROS 2 TF topic, and then compute the palm's position. For a calculation example, please refer to example/mc/se3_location.py