Joint Group Control
set_group_cmd()
set_group_cmd(
position_cmd: Dict[str, list[float]],
velocity_cmd: Dict[str, list[float]] | None = None,
torque_cmd: Dict[str, list[float]] | None = None
)
Sends position, velocity, and torque commands to one or more joint groups. position_cmd is required; the others are optional. Commands take effect immediately — interpolation is recommended to avoid sudden jumps.
| Parameter | Type | Description |
|---|---|---|
position_cmd | Dict[str, list[float]] | group name → target joint position list (rad) |
velocity_cmd | Dict[str, list[float]] | None | group name → target joint velocity list (rad/s) |
torque_cmd | Dict[str, list[float]] | None | group name → target joint torque list (Nm) |
Valid group names (depends on robot model; refer to hardware.json):
waist (5 DOF), head (2 DOF), left_manipulator (7 DOF), right_manipulator (7 DOF), left_end_effector, right_end_effector
The two end effectors can be used as raw command targets and expose a one-dimensional state via get_group_state(); however, get_group_motion_state() and get_group_motor_cfg() currently support only waist, head, left_manipulator, and right_manipulator — do not pass left_end_effector or right_end_effector to them.
Waist commands must contain five joint values. Its safe default position is [-1.25, 2.15, -0.918, 0, 0]; never command all waist joints to zero.
Example: upper-body control with interpolation
Targets are generated from "current reading + bounded offset" instead of hardcoded absolute poses (joint zero positions are not fixed; keep single-joint offsets within ±0.03 rad). Joint commands must be streamed continuously in state 4 (upper_body_tele_task):
import os
import time
os.environ.setdefault("FASTDDS_BUILTIN_TRANSPORTS", "UDPv4") # required on the robot
from fourier_aurora_client import AuroraClient
client = AuroraClient.get_instance(domain_id=123, robot_name="grw")
try:
time.sleep(1.0)
if not client.set_fsm_state(4):
raise RuntimeError("state change request not accepted")
deadline = time.monotonic() + 4.0
while client.get_fsm_state() != 4:
if time.monotonic() >= deadline:
raise RuntimeError("did not switch to upper_body_tele_task")
time.sleep(0.05)
init_pose = client.get_group_state("left_manipulator", key="position")
target_pose = list(init_pose)
target_pose[0] += 0.03
steps = 200
for i in range(steps + 1): # move to target
pose = [s + (t - s) * i / steps for s, t in zip(init_pose, target_pose)]
client.set_group_cmd({"left_manipulator": pose})
time.sleep(0.01)
for i in range(steps + 1): # return to start
pose = [t + (s - t) * i / steps for s, t in zip(init_pose, target_pose)]
client.set_group_cmd({"left_manipulator": pose})
time.sleep(0.01)
finally:
if client.get_fsm_state() == 4:
client.set_fsm_state(3) # back to the standing policy state
client.close()
get_group_state()
get_group_state(group_name: str, key: str = 'position') -> list[float]
Reads the current state of a specified joint group.
| Parameter | Type | Description |
|---|---|---|
group_name | str | Joint group name |
key | str | Data type to return — see table below |
key value | Description |
|---|---|
'position' | Joint positions (rad), default |
'velocity' | Joint velocities (rad/s) |
'effort' | Joint torques (Nm) |
Example
import os
import time
os.environ.setdefault("FASTDDS_BUILTIN_TRANSPORTS", "UDPv4") # required on the robot
from fourier_aurora_client import AuroraClient
client = AuroraClient.get_instance(domain_id=123, robot_name="grw")
try:
time.sleep(1.0) # wait for state data
pos = client.get_group_state("waist", key="position")
vel = client.get_group_state("waist", key="velocity")
print(f"waist position: {pos}")
print(f"waist velocity: {vel}")
finally:
client.close()
get_group_motion_state()
get_group_motion_state(group_name: str) -> int
Reads the current motion state of a specified joint group.
| Return value | Description |
|---|---|
0 | Idle |
1 | Moving |
2 | Stopping |
3 | Error |
While interpolation commands are streamed at 100 Hz in state 4, the motion state of left_manipulator stays 0 (idle). The return value does not reflect motion caused by teleoperation commands and must not be used to wait for "motion complete"; rely on the end of the command stream and convergence of get_group_state() positions instead.
Example
import os
import time
os.environ.setdefault("FASTDDS_BUILTIN_TRANSPORTS", "UDPv4") # required on the robot
from fourier_aurora_client import AuroraClient
client = AuroraClient.get_instance(domain_id=123, robot_name="grw")
try:
time.sleep(1.0) # wait for state data
state = client.get_group_motion_state("left_manipulator")
print(f"motion state: {state} (0=idle)")
finally:
client.close()