This page focuses on the motion‑related APIs:
move_jointmove_j_position_followregister_servo_joint_control_callbackset_max_joint_speed, set_max_joint_accel, set_max_finger_torqueIt assumes you already know the basics from the previous sections and have seen JointId and JointControlParam.
move_joint — blocking joint controlfrom 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}")
The
commandslist can contain any number of joints, allowing multi‑joint moves in one call.
move_j_position_follow — follow controlimport 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)
Notes:
MoveJPositionFollowParam entries.register_servo_joint_control_callback — servo loopregister_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.
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.
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.
set_max_joint_speedfrom 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_accelfrom 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_torquefrom 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.
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.