Motion Control APIs in Detail

A deeper look at ApexHand motion control, follow control and safety limits.

This page focuses on the motion‑related APIs:

  • Blocking joint motion: move_joint
  • Follow control: move_j_position_follow
  • Servo‑loop callback: register_servo_joint_control_callback
  • Safety limits: set_max_joint_speed, set_max_joint_accel, set_max_finger_torque

It assumes you already know the basics from the previous sections and have seen JointId and JointControlParam.

move_joint — blocking joint control

move_joint_basic_en.py
from dexcelbot_apexhand_sdk import (
    DexcelBot,
    JointId,
    create_joint_control_param,
    ErrorCode,
)

bot = DexcelBot()
# connect + enable fingers ...

cmds = [
    create_joint_control_param(
        joint_id=JointId.JOINT_ID_THUMB_MCP,
        position=0.5,
        velocity=0.2,
        acceleration=0.0,
    )
]

result = bot.move_joint(cmds)
if result != ErrorCode.ERROR_CODE_OK:
    raise RuntimeError(f"move_joint failed: {result}")
  • Blocking: returns when motion finishes or fails.
  • Good for:
    • Simple “go to” motions (open / close / pose).
    • Low‑frequency, scripted sequences.

The commands list can contain any number of joints, allowing multi‑joint moves in one call.

move_j_position_follow — follow control

follow_basic_en.py
import time
from dexcelbot_apexhand_sdk import (
    DexcelBot,
    JointId,
    create_move_j_position_follow_param,
    ErrorCode,
)

bot = DexcelBot()
# connect + enable fingers ...

for i in range(100):
    position = 0.1 + 0.4 * (i / 99)
    params = [
        create_move_j_position_follow_param(
            joint_id=JointId.JOINT_ID_INDEX_MCP_0,
            position=position,
        )
    ]
    result = bot.move_j_position_follow(params)
    if result != ErrorCode.ERROR_CODE_OK:
        print("move_j_position_follow failed:", result)
        break
    time.sleep(0.01)
  • Non‑blocking: returns immediately after queuing the targets.
  • Good for:
    • Streaming target points from a planner or tele‑op device.
    • Smooth trajectory execution without manually computing interpolation.

Notes:

  • Multi‑joint commands are allowed: just push several MoveJPositionFollowParam entries.
  • To get smoother trajectories, keep the send period reasonably small and stable.

register_servo_joint_control_callback — servo loop

register_servo_joint_control_callback exposes a high‑frequency servo loop:
the SDK periodically calls your callback with the current joint states and an editable list of ServoJointParam.

Callback signature

def servo_callback(joint_states, servo_params):
    # joint_states: JointStates
    # servo_params: List[ServoJointParam] provided by the SDK
    ...

You modify servo_params in place (for example, setting desired position / velocity), and the SDK sends them to the controller.

Example — simple sine tracking

servo_control_en.py
import math
import time
from dexcelbot_apexhand_sdk import (
    DexcelBot,
    JointId,
    ErrorCode,
)

bot = DexcelBot()
# connect + enable fingers ...

start_time = time.time()

def servo_callback(joint_states, servo_params):
    t = time.time() - start_time
    target_pos = 0.3 * math.sin(2 * math.pi * 0.5 * t)  # 0.5 Hz sine

    for p in servo_params:
        if p.joint_id == JointId.JOINT_ID_INDEX_MCP_0:
            p.position = target_pos
            p.velocity = 0.5

result = bot.register_servo_joint_control_callback(servo_callback, freq_hz=100)
if result != ErrorCode.ERROR_CODE_OK:
    raise RuntimeError("Failed to register servo control callback")

time.sleep(10.0)
bot.unregister_servo_joint_control_callback()

Keep the computation inside the callback lightweight to meet the requested freq_hz. Heavy processing should be offloaded to other threads/processes.

Safety limits

set_max_joint_speed

max_speed_en.py
from dexcelbot_apexhand_sdk import DexcelBot, MaxJointSpeed, JointId

bot = DexcelBot()

limits = []
for jid in JointId:
    s = MaxJointSpeed()
    s.joint_id = jid
    s.speed = 1.0  # rad/s
    limits.append(s)

bot.set_max_joint_speed(limits)

If a requested limit is too high, the function returns ERROR_CODE_OUT_OF_RANGE.

set_max_joint_accel

max_accel_en.py
from dexcelbot_apexhand_sdk import DexcelBot, MaxJointAccel, JointId

bot = DexcelBot()

accels = []
for jid in JointId:
    a = MaxJointAccel()
    a.joint_id = jid
    a.accel = 2.0  # rad/s²
    accels.append(a)

bot.set_max_joint_accel(accels)

set_max_finger_torque

max_torque_en.py
from dexcelbot_apexhand_sdk import DexcelBot, MaxFingerTorque, FingerId

bot = DexcelBot()

torques = []
for fid in FingerId:
    t = MaxFingerTorque()
    t.finger_id = fid
    t.torque = 80.0  # limit to 80%
    torques.append(t)

bot.set_max_finger_torque(torques)

For any real‑world contact or grasping tasks, you should always configure reasonable limits on speed, acceleration and torque to ensure safety.

Combined example — safe grasp motion

grasp_en.py
from dexcelbot_apexhand_sdk import (
    DexcelBot,
    FingerId,
    JointId,
    MaxFingerTorque,
    MaxJointSpeed,
    MaxJointAccel,
    create_joint_control_param,
    ErrorCode,
)

bot = DexcelBot()
# connect + enable fingers ...

# 1. Safety limits
torques = []
for fid in FingerId:
    t = MaxFingerTorque()
    t.finger_id = fid
    t.torque = 60.0
    torques.append(t)
bot.set_max_finger_torque(torques)

speeds = []
accels = []
for jid in JointId:
    s = MaxJointSpeed()
    s.joint_id = jid
    s.speed = 0.8
    speeds.append(s)

    a = MaxJointAccel()
    a.joint_id = jid
    a.accel = 1.5
    accels.append(a)

bot.set_max_joint_speed(speeds)
bot.set_max_joint_accel(accels)

# 2. Simple grasp motion (illustrative)
cmds = [
    create_joint_control_param(JointId.JOINT_ID_INDEX_PIP, position=0.9, velocity=0.3),
    create_joint_control_param(JointId.JOINT_ID_MIDDLE_PIP, position=0.9, velocity=0.3),
    create_joint_control_param(JointId.JOINT_ID_RING_PIP, position=0.9, velocity=0.3),
    create_joint_control_param(JointId.JOINT_ID_PINKY_PIP, position=0.9, velocity=0.3),
]

result = bot.move_joint(cmds)
if result != ErrorCode.ERROR_CODE_OK:
    print("Grasp motion failed:", result)

With this API set you can implement most joint‑space trajectories and safety behaviors for ApexHand. The next page covers state reading and tactile images in more detail.

源升智能机器人(深圳)有限公司 • © 2026 粤ICP备2025470595号-1