运动控制 API 详解

详细说明 ApexHand 中的关节控制相关接口。

本节聚焦 ApexHand SDK 的 运动控制相关接口,包括:

  • 阻塞式位置控制:move_joint
  • 跟随控制:move_j_position_follow
  • 高级伺服控制回调:register_servo_joint_control_callback
  • 安全限制:set_max_joint_speedset_max_joint_accelset_max_finger_torque

假定你已阅读「枚举与结构体概览」,并了解 JointIdJointControlParam 等基础类型。

move_joint 阻塞式位置控制

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

bot = DexcelBot()
# 省略 connect() 与 set_all_fingers_enabled() ...

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 失败: {result}")
  • 特性:阻塞式,直到到达目标位置或失败才返回。
  • 适用场景
    • 预先规划好的单次或少次数动作(如「张开/握紧」)。
    • 不需要高频反馈闭环的简单动作。

commands任意数量关节 的组合,可在一次调用中同时下发多关节目标。

move_j_position_follow 跟随控制

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

bot = DexcelBot()
# 省略 connect() 与 set_all_fingers_enabled() ...

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 失败:", result)
        break
    time.sleep(0.01)
  • 特性:非阻塞式,内部对相邻目标做样条/插值规划。
  • 适用场景
    • 上位机以不完全固定的周期发送位置目标(例如轨迹跟随)。
    • 需要更平滑的运动效果。

注意事项:

  • 同样支持多关节组合控制,只需在 params 中加入多个 MoveJPositionFollowParam
  • 为获得更平滑轨迹,应尽量保持发送周期较小且尽量稳定。

register_servo_joint_control_callback 伺服回调

register_servo_joint_control_callback 提供了高级的 闭环伺服控制 能力:SDK 会在内部周期性调用你注册的回调,将当前关节状态传入,并期望你填充目标控制指令列表。

回调函数签名

在 Python 中,回调的预期形式为:

def servo_callback(joint_states, servo_params):
    # joint_states: JointStates
    # servo_params: List[ServoJointParam](由 SDK 创建并传入)
    ...

你需要在回调中修改 servo_params(例如设置每个关节的目标位置与速度),SDK 会自动将这些值发送到底层控制器。

示例:简易正弦跟随

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

bot = DexcelBot()
# 省略 connect() 与 set_all_fingers_enabled() ...

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 正弦

    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("注册伺服控制回调失败")

time.sleep(10.0)  # 运行一段时间
bot.unregister_servo_joint_control_callback()

伺服回调适合实现基于关节状态的自定义控制律(如阻抗控制、力控制上层逻辑等),请确保回调函数内部运算时间足够短,以满足给定的 freq_hz 要求。

安全限制设置

set_max_joint_speed

设置每个关节的最大速度限制:

max_speed.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  # 示例:为所有关节设置 1 rad/s
    limits.append(s)

bot.set_max_joint_speed(limits)

如果给定速度超出允许范围,函数会返回 ERROR_CODE_OUT_OF_RANGE

set_max_joint_accel

设置每个关节的最大加速度限制:

max_accel.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  # 示例:统一 2 rad/s²
    accels.append(a)

bot.set_max_joint_accel(accels)

set_max_finger_torque

设置每个手指的最大扭矩(单位为 0–100%):

max_torque.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  # 将所有手指限制在 80% 以内
    torques.append(t)

bot.set_max_finger_torque(torques)

建议在任何实际接触或抓取任务中,都先配置合理的速度、加速度和扭矩限制,以保证安全。

综合示例:安全限幅 + 基本抓取动作

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

bot = DexcelBot()
# 1. 连接与使能略

# 2. 配置安全限制
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)

# 3. 简单抓取动作(示意)
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("抓取动作失败:", result)

通过本节你可以完成大部分基于关节空间的轨迹控制。下一节将介绍 状态读取与触觉图像,帮助你在任务中实时感知 ApexHand 的运动与接触情况。

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