Synria Follower Arm Python SDK v1.1.1
This document corresponds to Alicia-M SDK v1.1.1, compatible with Synria Communication Protocol v1.0.6. If you are interfacing directly with the underlying serial frames, please also refer to the "Synria Communication Protocol" page of this series.
1. Introduction
The Alicia-M SDK is a Python development toolkit for controlling the Synria Alicia-M series six-axis follower arms and grippers. The SDK encapsulates capabilities such as serial communication, protocol encoding/decoding, device status polling, PV/MIT control, gripper control, kinematics, trajectory planning, teleoperation, and device settings.
The SDK hides implementation details such as underlying protocol frames, register addresses, CRC checks, and status polling threads. Client code typically only needs to create a robot object via create_robot() and then call clear Python methods to complete device connection, status reading, joint motion, gripper control, mode switching, kinematics computation, trajectory planning, and maintenance configuration.
For a normal development workflow, it is recommended to use only the unified entry alicia_m_sdk.create_robot() to create a robot object, and then complete connection, status reading, and motion control through SynriaRobotAPI.
import alicia_m_sdk
robot = alicia_m_sdk.create_robot(port="COM37")
robot.set_robot_state(target_joints=[0, 30, 0, 0, -30, 0], joint_format="deg")
robot.disconnect()
1.1 Core Capabilities
- Unified control entry:
create_robot()creates aSynriaRobotAPIinstance, covering connection, status reading, motion control, gripper, diagnostics, user settings, and trajectory interfaces. - Automatic serial port discovery: When
port="", it automatically scans for available serial ports; you can also explicitly specify WindowsCOM37or Linux/dev/ttyACM0. - PV / MIT dual modes: PV mode is suitable for regular point-to-point motion, and MIT mode is suitable for impedance control, drag teaching, low-latency teleoperation, and frame-by-frame control.
- Joint + gripper coordination:
set_robot_state()can control the 6 joints and the gripper simultaneously, or move only the gripper or only the joints. - Real-time status cache: Background polling maintains angle, gripper, velocity, torque, and operating status; extended polling can read Kp, Kd, interpolation velocity, and temperature.
- RoboCore integration: Supports forward/inverse kinematics, joint trajectories, Cartesian trajectories, and trajectory CSV saving.
- Teleoperation support: Built-in Alicia-D to Alicia-M URDF limit mapping teleoperation workflow.
- Device maintenance interfaces: Provides self-test, enable/disable, mode switching, zero-point setting, gripper type, and user settings read/write.
2. Installation and Connection
2.1 Environment Requirements
- Python
>=3.11 - Alicia-M follower arm and USB cable
- Usable on Windows, Linux, and macOS
- On Linux, confirm that the current user has serial port access permissions
2.2 Install from PyPI
Install the stable version:
pip install alicia-m-sdk
Install the pre-release version:
pip install --pre alicia-m-sdk
The PyPI package name uses hyphens: alicia-m-sdk. The import name in Python code uses underscores: import alicia_m_sdk.
2.3 Install from Source
If you need to run the complete examples/ in the repository, it is recommended to install from source:
git clone https://github.com/Synria-Robotics/Alicia-M-SDK.git
cd Alicia-M-SDK
conda create -n msdk python=3.11
conda activate msdk
pip install -e .
Optional dependencies are split by functionality:
pip install -e ".[planning]" # scipy trajectory planning
pip install -e ".[visualization]" # matplotlib trajectory plotting
pip install -e ".[sparkvis]" # WebSocket / SparkVis
pip install -e ".[teleop]" # Alicia-D -> Alicia-M teleoperation
pip install -e ".[torch]" # RoboCore torch backend
pip install -e ".[all]" # Common optional dependencies
2.4 Serial Port Permissions
Windows and macOS usually do not require additional configuration. On Linux, if Permission denied appears, you can handle it as follows.
# Recommended: add the current user to the dialout group; takes effect after logging out and back in
sudo usermod -a -G dialout $USER
# Temporary debugging: open up permissions for the current USB serial port
sudo chmod 666 /dev/ttyUSB* /dev/ttyACM*
# Permanent rule: allow access to ttyUSB/ttyACM devices
echo 'KERNEL=="ttyUSB*|ttyACM*", MODE="0666"' | sudo tee /etc/udev/rules.d/99-serial.rules
sudo udevadm control --reload-rules
sudo udevadm trigger
2.5 Hardware Connection Verification
After powering on the Alicia-M and connecting it to the computer via USB, first confirm that the system can see the serial port:
| System | Check Method |
|---|---|
| Windows | Open Device Manager and view the COM ports |
| Linux | ls -l /dev/ttyUSB* /dev/ttyACM* |
| macOS | ls /dev/cu.* |
Then run the version read example to verify that the SDK can communicate normally:
# Windows
python examples/00_demo_read_version.py --port COM37
# Linux
python examples/00_demo_read_version.py --port /dev/ttyACM0
If --port is not passed, the SDK will attempt to automatically scan for serial ports.
3. Quick Start
3.1 Use a Context Manager
It is recommended to use with to manage the connection lifecycle. When entering with, the SDK ensures it is connected, and when leaving, it automatically disconnects the serial port.
import alicia_m_sdk
with alicia_m_sdk.create_robot(port="COM37", control_mode="pv") as robot:
robot.set_robot_state(
target_joints=[0, 30, 0, 0, -30, 0],
gripper_value=500,
joint_format="deg",
speed=15,
gripper_speed=100,
)
state = robot.get_robot_state("all")
print(state.angles) # 6 joint angles, in rad
print(state.gripper) # Gripper opening value, range 0~1000
3.2 Automatically Scan Serial Ports
port defaults to an empty string, which means automatically discovering the Alicia-M serial port. Suitable for scenarios with few devices and for development debugging.
import alicia_m_sdk
robot = alicia_m_sdk.create_robot()
print(robot.connected_port)
robot.disconnect()
3.3 Manually Specify the Serial Port
For production scripts or multi-device environments, it is recommended to manually specify the serial port to avoid connecting to the wrong device.
import alicia_m_sdk
# Windows
robot = alicia_m_sdk.create_robot(port="COM37")
# Linux
robot = alicia_m_sdk.create_robot(port="/dev/ttyACM0")
if robot.is_connected():
print("Alicia-M connected")
robot.disconnect()
3.4 Deferred Connection
If you want to first create the object and then connect at an appropriate time, you can set auto_connect=False.
import alicia_m_sdk
robot = alicia_m_sdk.create_robot(
port="COM37",
auto_connect=False,
sync_control_mode=False,
)
robot.connect(timeout=5.0)
print(robot.get_robot_state("version"))
robot.disconnect()
sync_control_mode=False is suitable for scenarios where you only read the version number, status, etc., and do not need to immediately synchronize the control mode, which can reduce the wait during the connection phase.
4. Core Control Workflow
4.1 PV Point-to-Point Motion
In PV mode, the firmware handles position and velocity control, suitable for point-to-point movement, returning to zero, normal action execution, and trajectory playback.
import alicia_m_sdk
with alicia_m_sdk.create_robot(port="COM37", control_mode="pv") as robot:
if robot.control_mode.value != "pv":
robot.switch_mode("pv")
ok = robot.set_robot_state(
target_joints=[0, 30, 0, 0, -30, 0],
joint_format="deg",
speed=20,
wait_for_completion=True,
)
print("arrived:", ok)
Common parameters:
| Parameter | Description |
|---|---|
target_joints | 6 joint target angles; uses degrees when joint_format="deg", radians when "rad" |
speed | Joint motion speed parameter; the larger the value, the faster the motion |
wait_for_completion | Whether to wait until motion arrives before returning |
gripper_value | Optional gripper target value, range 0~1000 |
gripper_speed | Gripper speed parameter |
4.2 Control the Gripper Only
If target_joints=None and gripper_value is passed in, the SDK only moves the gripper and does not change the current joint positions.
with alicia_m_sdk.create_robot(port="COM37") as robot:
# Method 1: use set_robot_state
robot.set_robot_state(
target_joints=None,
gripper_value=1000,
gripper_speed=100,
)
# Method 2: use the gripper shortcut interface
robot.set_gripper_target("open")
robot.set_gripper_target("close")
robot.set_gripper_target(value=500)
The gripper target value ranges from 0~1000. Typically 0 is close to closed and 1000 is close to open; the actual opening distance depends on the installed gripper type and firmware configuration.
4.3 Coordinated Joint and Gripper Motion
The same set_robot_state() call can issue both joint and gripper targets simultaneously.
with alicia_m_sdk.create_robot(port="COM37", control_mode="pv") as robot:
robot.set_robot_state(
target_joints=[0, 20, -10, 0, -35, 0],
gripper_value=300,
joint_format="deg",
speed=15,
gripper_speed=80,
)
If a certain type of target is passed None, it means keeping the current state:
# Only move the joints; the gripper keeps its current value
robot.set_robot_state(
target_joints=[0, 10, 0, 0, -20, 0],
gripper_value=None,
joint_format="deg",
)
# Only move the gripper; the joints keep their current angles
robot.set_robot_state(
target_joints=None,
gripper_value=600,
)
4.4 MIT Impedance Control
MIT mode is used for impedance control, drag teaching, and high-frequency teleoperation. The control law can be understood as:
tau = kp * (pos_ref - pos_cur) + kd * (vel_ref - vel_cur) + t_ref
In MIT mode, set_robot_state() sends parameters such as position, velocity, torque, Kp, and Kd. You can still use the point-to-point style of writing, with the SDK responsible for interpolation and arrival judgment.
with alicia_m_sdk.create_robot(port="COM37", control_mode="mit") as robot:
if robot.control_mode.value != "mit":
robot.switch_mode("mit")
robot.set_robot_state(
target_joints=[0, 30, 0, 0, -30, 0],
gripper_value=500,
joint_format="deg",
speed=30,
use_interpolation=True,
kp=[150.0] * 7,
kd=[2.0] * 7,
torque=[0.0] * 7,
vel_ref=[0.0] * 7,
wait_for_completion=True,
)
MIT parameter format:
| Parameter | Description |
|---|---|
kp | Position loop gain; can pass a scalar, a 6-joint list, or a 7-motor list |
kd | Velocity loop gain; can pass a scalar, a 6-joint list, or a 7-motor list |
torque | Feedforward torque, in N·m; can pass a scalar, a 6-joint list, or a 7-motor list |
vel_ref | Target velocity, in rad/s; can pass a scalar, a 6-joint list, or a 7-motor list |
use_interpolation | Whether to use linear trajectory interpolation in MIT mode |
When kp, kd, torque, or vel_ref are explicitly passed 0 or 0.0, they represent real zero values. Only when None is passed will the SDK use the corresponding default value.
4.5 MIT Low-Latency Frame-by-Frame Control
send_mit_command() is suitable for low-latency and high-frequency control scenarios. The caller needs to maintain the control frequency themselves and prepare MIT parameters for each motor.
import time
import alicia_m_sdk
from alicia_m_sdk import MitParams
with alicia_m_sdk.create_robot(port="COM37", control_mode="mit") as robot:
params = [
MitParams(pos_ref=0.0, vel_ref=0.0, t_ref=0.0, kp=120.0, kd=1.5)
for _ in range(7)
]
for _ in range(200):
robot.send_mit_command(params, gripper=500)
time.sleep(0.01) # 100 Hz
This interface does not do complete trajectory planning for the caller, nor does it wait for arrival at the target. It is more suitable for projects that already have an external controller or a real-time teleoperation loop.
5. Status Reading
After the SDK connects, it maintains a device status cache in the background. Regular status reads do not block waiting for a serial response every time, so they are suitable for frequent calls within a control loop.
5.1 Read Joints and Gripper
with alicia_m_sdk.create_robot(port="COM37") as robot:
joints = robot.get_robot_state("joint")
joint_gripper = robot.get_robot_state("joint_gripper")
print(joints) # [j0, j1, j2, j3, j4, j5], in rad
print(joint_gripper["angles"]) # 6 joint angles, in rad
print(joint_gripper["gripper"]) # Gripper value, range 0~1000
5.2 Read the Complete JointState
info_type="all" returns the complete status object, suitable for programs that need to view angle, velocity, torque, and extended fields at the same time.
with alicia_m_sdk.create_robot(port="COM37", extended_polling=True) as robot:
state = robot.get_robot_state("all")
print(state.angles) # Joint angles, rad
print(state.gripper) # Gripper value, 0~1000
print(state.velocities) # Joint velocities, rad/s
print(state.torques) # Joint torques, N*m
print(state.kps) # MIT Kp, available after extended polling is enabled
print(state.kds) # MIT Kd, available after extended polling is enabled
print(state.linear_vels) # Interpolation velocity, available after extended polling is enabled
print(state.temperatures) # Coil temperature, available after extended polling is enabled
5.3 Query Type Descriptions
info_type | Returned Content | Notes |
|---|---|---|
"joint" | list[float] | 6 joint angles, in rad |
"joint_gripper" | dict | angles and gripper |
"velocity" | list[float] or None | Joint velocities, in rad/s |
"torque" | list[float] or None | Joint torques, in N·m |
"linear_vels" | list[float] or None | Interpolation velocity, requires extended polling |
"temperatures" | list[float] or None | Coil temperature, requires extended polling |
"all" | JointState or None | Complete status object |
"version" | VersionInfo or None | Firmware version, hardware version, etc. |
"status" | RobotStatus or None | Operating status |
"control_mode" | list[dict] or None | One-time query of each motor's control mode |
5.4 Extended Polling
By default, polling only reads basic status for broader compatibility. When you need fields such as Kp, Kd, interpolation velocity, and temperature, you can enable extended polling.
robot = alicia_m_sdk.create_robot(port="COM37")
robot.set_extended_polling(True)
state = robot.get_robot_state("all")
print(state.kps, state.kds, state.linear_vels, state.temperatures)
robot.set_extended_polling(False)
robot.disconnect()
You can also enable it directly at creation time:
robot = alicia_m_sdk.create_robot(
port="COM37",
extended_polling=True,
)
6. API Reference
6.1 create_robot()
create_robot() is the recommended entry for creating a robot. It sets up the RoboCore backend, loads the robot model, creates the SynriaRobotAPI, and by default automatically connects the device.
robot = alicia_m_sdk.create_robot(
port="", # Empty string means automatically discover the serial port
version="auto", # Automatically identify the model version from firmware; can also explicitly pass "v1_0" / "v1_1" / "v1_2"
variant=None, # URDF variant; uses the default follower when None
control_aim=None, # "leader" / "follower" / None; None means auto-detect or use the device's current configuration
control_mode=None, # "pv" / "mit" / None; None means sync the firmware's current mode on connection
sync_control_mode=True, # Whether to read and sync the firmware control mode on connection
baudrate=1_000_000, # Serial port baud rate
backend="cpp", # RoboCore backend: "cpp" / "numpy" / "torch"
debug_mode=False, # Whether to enable DEBUG logging
auto_connect=True, # Whether to connect immediately after creation
extended_polling=False, # Whether to enable extended status polling
)
Parameter descriptions:
| Parameter | Recommended Value | Description |
|---|---|---|
port | "" or the actual serial port | Auto-discover or manually specify the serial port |
version | "auto" | Automatically identify the hardware/model version; can be explicitly specified when using kinematics offline |
control_aim | None | Usually the Alicia-M acts as a follower; teleoperation scripts explicitly pass "follower" |
control_mode | None | Let the SDK follow the device's current mode; pass "pv" or "mit" when a fixed mode is needed |
sync_control_mode | True | Can be set to False to speed up connection when only reading the version or status |
backend | "cpp" | Uses the RoboCore C++ backend by default; can switch to "numpy" when there is no C++ extension |
extended_polling | False | Only enable when extended status fields are needed |
6.2 set_robot_state()
set_robot_state() is the most commonly used motion control interface. It automatically takes the PV or MIT path based on the current control mode.
ok = robot.set_robot_state(
target_joints=[0, 30, 0, 0, -30, 0],
gripper_value=500,
joint_format="deg",
speed=40,
gripper_speed=100,
wait_for_completion=True,
use_interpolation=True,
kp=None,
kd=None,
torque=None,
vel_ref=None,
)
| Parameter | Description |
|---|---|
target_joints | 6 joint target angles; None means do not change the joints |
gripper_value | Gripper target value 0~1000; None means do not change the gripper |
joint_format | "deg" or "rad" |
speed | Joint motion speed parameter |
gripper_speed | Gripper motion speed parameter |
wait_for_completion | Whether to wait for arrival at the target |
use_interpolation | Whether to use linear interpolation in MIT mode |
kp / kd | MIT impedance gains |
torque / vel_ref | MIT feedforward torque and target velocity |
The return value is a boolean, indicating whether the SDK considers the action to have been successfully completed or successfully issued.
6.3 get_robot_state()
version = robot.get_robot_state("version")
status = robot.get_robot_state("status")
modes = robot.get_robot_state("control_mode")
state = robot.get_robot_state("all")
version, status, and all mainly come from the background cache; control_mode sends a control mode query frame once and waits for the response. Within a control loop, you should prefer reading cache-type status to avoid frequent blocking queries.
6.4 Mode Switching and Enabling
robot.enable_robot()
robot.disable_robot()
robot.switch_mode("pv")
robot.switch_mode("mit")
robot.torque_control("off") # Release force in MIT mode
robot.torque_control("on") # Restore in MIT mode
switch_mode() executes the disable, switch, enable flow. During switching, the follower arm is briefly disabled, so make sure the robotic arm is in a safe pose.
6.5 Gripper Type and User Settings
The Alicia-M supports writing the gripper type into the device's user settings. SDK v1.1.1 supports string, enum, or config-value forms.
with alicia_m_sdk.create_robot(port="COM37") as robot:
robot.set_gripper_type("50mm")
robot.set_gripper_type("100mm")
settings = robot.get_user_settings(timeout=1.0)
print(settings.values)
18_demo_user_settings.py also provides command-line examples:
python examples/18_demo_user_settings.py --port COM37
python examples/18_demo_user_settings.py --port COM37 --gripper-type 10 --yes
python examples/18_demo_user_settings.py --port /dev/ttyACM0 --gripper-type 40 --yes
User settings are saved on the device side and affect subsequent gripper actions. Before writing, confirm that the device is in a safe state and that the gripper type matches the actual hardware.
6.6 Gripper Gripping Parameters
The SDK provides get_gripper_params() and set_gripper_params() to read or write the gripper gripping parameters corresponding to protocol 0x17.
with alicia_m_sdk.create_robot(port="COM37") as robot:
params = robot.get_gripper_params(mask=0, aim="follower")
print(params)
result = robot.set_gripper_params(
values={"force": 0.5},
aim="follower",
save=False,
readback=True,
)
print(result)
set_gripper_params(..., save=False) by default only makes the parameters take effect immediately and does not actively write to the power-off save area, suitable for debugging gripping force, feedforward torque, and force-control parameters. After confirming that the parameters meet expectations, you can explicitly pass save=True to request the device to save the current complete gripper parameter configuration; a save write may be slower than a normal write, and the SDK will use a response wait time of at least 3 seconds.
The parameter names and mask bits exposed by different firmware may differ. In engineering, it is recommended to first use 15_demo_gripper_params.py to read the current parameters, then confirm the fields to write according to the protocol documentation.
6.7 Kinematics and Trajectory Planning
When RoboCore is available, the SDK loads the Alicia-M model and provides FK, IK, and trajectory planning interfaces.
with alicia_m_sdk.create_robot(port="COM37", version="auto") as robot:
pose = robot.get_pose()
print(pose["position"])
print(pose["quaternion_xyzw"])
fk = robot.compute_forward_kinematics(
joints=[0, 30, 0, 0, -30, 0],
joint_format="deg",
)
ik = robot.set_pose(
target_pose=pose["transform"],
method="dls",
execute=False,
)
print(ik["success"])
Joint trajectory planning and execution:
waypoints = [
[0.0, 0.0, 0.0, 0.0, -0.3, 0.0],
[0.0, 0.4, 0.0, 0.0, -0.6, 0.0],
[0.0, 0.2, 0.2, 0.0, -0.4, 0.0],
]
traj = robot.plan_joint_trajectory(
waypoints=waypoints,
planner_type="b_spline",
duration=5.0,
frequency=200.0,
)
if traj.get("success"):
robot.execute_planned_joint_trajectory(traj, speed=100.0)
Common trajectory interfaces:
| Interface | Purpose |
|---|---|
get_pose() | Read the current joint state and compute the end-effector pose |
compute_forward_kinematics() | Compute FK for the specified joint angles |
set_pose() | IK solving, with the option to execute to the target pose |
plan_joint_trajectory() | Plan a joint-space trajectory |
plan_cartesian_trajectory() | Plan a Cartesian-space trajectory |
execute_planned_joint_trajectory() | Execute a planned joint trajectory |
move_joint_trajectory() | Smoothly move from the current state to the target joint angles |
move_cartesian_linear() | Execute a Cartesian straight-line trajectory |
7. Detailed Example Programs
The scripts in the examples/ directory cover the complete usage workflow, from connection verification to teleoperation, trajectory planning, and device settings.
7.1 Demo Tour
When connecting to the Alicia-M for the first time, it is recommended to verify in the following order: first confirm communication, then check status, and finally do motion control:
- Run
00_demo_read_version.pyto confirm that the SDK can connect to the device and read the firmware version. - Run
02_demo_read_status.pyor03_demo_read_states.pyto confirm that the operating status, control mode, joint angles, and gripper value are read normally. - Run
06_demo_move_gripper.pyor07_demo_move_joint.pyto verify gripper and joint motion in a safe space.
python examples/00_demo_read_version.py --port COM37
python examples/03_demo_read_states.py --port COM37
python examples/07_demo_move_joint.py --port COM37 --speed 15
python examples/00_demo_read_version.py --port /dev/ttyACM0
python examples/03_demo_read_states.py --port /dev/ttyACM0
python examples/07_demo_move_joint.py --port /dev/ttyACM0 --speed 15
If the serial port name is uncertain, you can first not pass --port and let the SDK scan automatically; when you need to fix the device in a production environment, explicitly specify Windows COM37 or Linux /dev/ttyACM0.
7.2 Basic Functions
| No. | File | Purpose |
|---|---|---|
| 00 | 00_demo_read_version.py | Read firmware version, hardware version, and device information; recommended as the first step for connection verification |
| 01 | 01_demo_diagnostic.py | Run device self-test to check whether communication and device response are normal |
| 02 | 02_demo_read_status.py | Read control mode and operating status |
| 03 | 03_demo_read_states.py | Loop-print joint angles, gripper, velocity, torque, and extended status |
| 04 | 04_demo_switch_mode.py | Switch PV / MIT control mode |
| 05 | 05_demo_disable_enable.py | Demonstrate disabling and enabling |
Common commands:
python examples/00_demo_read_version.py --port COM37
python examples/02_demo_read_status.py --port COM37
python examples/03_demo_read_states.py --port COM37 --extend
03_demo_read_states.py --extend calls set_extended_polling(True), suitable for checking the Kp, Kd, interpolation velocity, and temperature fields.
7.3 Motion Control
| No. | File | Purpose |
|---|---|---|
| 06 | 06_demo_move_gripper.py | Control gripper opening/closing independently |
| 07 | 07_demo_move_joint.py | PV mode joint motion |
| 08 | 08_demo_move_full_arm.py | PV mode coordinated joint + gripper motion |
| 09 | 09_demo_move_joint_mit.py | MIT mode joint motion |
| 10 | 10_demo_move_full_arm_mit.py | MIT mode coordinated joint + gripper motion |
Common commands:
python examples/06_demo_move_gripper.py --port COM37
python examples/07_demo_move_joint.py --port COM37 --speed 15
python examples/10_demo_move_full_arm_mit.py --port COM37
It is recommended for first-time use to run the PV examples first, and after confirming that the space is safe and the direction is correct, then proceed to the MIT examples.
7.4 Kinematics and Trajectories
| No. | File | Purpose |
|---|---|---|
| 11 | 11_demo_forward_kinematics.py | Read the current joint angles and compute the end-effector pose |
| 12 | 12_demo_inverse_kinematics.py | Demonstrate IK solving and optional execution |
| 16 | 16_demo_joint_traj.py | Joint-space trajectory planning, saving, plotting, and execution |
Common commands:
python examples/11_demo_forward_kinematics.py --port COM37
python examples/12_demo_inverse_kinematics.py --port COM37
python examples/16_demo_joint_traj.py --port COM37 --plot
python examples/16_demo_joint_traj.py --port /dev/ttyACM0 --planner multi_segment --segment-type quintic
16_demo_joint_traj.py supports manually recording waypoints, automatically generating waypoints, or loading waypoints from a file. After planning succeeds, it saves the trajectory CSV and can optionally plot the target trajectory, feedback trajectory, and velocity curve.
7.5 Advanced Applications and Device Settings
| No. | File | Purpose |
|---|---|---|
| 13 | 13_demo_reset_zero.py | Set the current pose as the zero position |
| 14 | 14_demo_teleop_mapped.py | Alicia-D to Alicia-M URDF limit mapping teleoperation |
| 15 | 15_demo_gripper_params.py | Read and write gripper gripping parameters |
| 17 | 17_demo_mit_torque_switch.py | MIT mode torque switch test |
| 18 | 18_demo_user_settings.py | Read and write user settings, e.g., gripper type |
15_demo_gripper_params.py corresponds to the protocol 0x17 gripper gripping parameters. When writing the target gripping force, feedforward torque, maximum holding torque, force-control proportion, and integral parameters, the SDK first performs range validation; the default --gripper-type auto attempts to read the current gripper type and limits the input according to the precise protocol range of the small or large gripper. Writing only takes effect immediately by default; to save through a power cycle, explicitly add --save; --save is only used for writing parameters and should not be used when reading.
python examples/15_demo_gripper_params.py --port COM37 --read
python examples/15_demo_gripper_params.py --port COM37 --gripper-type auto --target-force 35 --max-hold-torque 2.5
python examples/15_demo_gripper_params.py --port COM37 --gripper-type auto --target-force 30 --save
python examples/15_demo_gripper_params.py --port /dev/ttyACM0 --gripper-type auto --read
Teleoperation example:
# Windows
python examples/14_demo_teleop_mapped.py --leader-port COM63 --port COM51 --mode mit
# Linux
python examples/14_demo_teleop_mapped.py --leader-port /dev/ttyACM0 --port /dev/ttyACM1 --mode mit
# PV mode teleoperation
python examples/14_demo_teleop_mapped.py --leader-port COM63 --port COM51 --mode pv
Common teleoperation parameters:
| Parameter | Default | Description |
|---|---|---|
--mode | mit | Follower control mode, options pv / mit |
--leader-port | COM63 | Alicia-D teaching arm serial port |
--port / --follower-port | COM51 | Alicia-M follower arm serial port |
--follower-version | v1_1 | Alicia-M model version |
--frequency | 100.0 | Control loop frequency, in Hz |
--speed | 200.0 | Follower motion speed parameter |
--interpolation | Off | Enable linear interpolation in MIT mode |
--home | Off | Move the Follower to zero before teleoperation |
--verbose | Off | Print mapping status |
Before starting teleoperation, confirm that both the Alicia-D and the Alicia-M are in safe positions and that there are no people or obstacles in the workspace. When stopping teleoperation, it is recommended to first move the follower arm back to a safe pose, then interrupt the program in the terminal.
8. Common Parameter Adjustment Scenarios
8.1 PV Motion
| Symptom | Recommendation |
|---|---|
| Motion too fast | Lower speed or gripper_speed |
| Still a noticeable error after arrival | Check whether the target angle unit matches joint_format |
| Gripper action direction does not match expectations | Confirm that the gripper type configuration matches the actual hardware |
| Multi-segment motion not smooth enough | Use plan_joint_trajectory() or 16_demo_joint_traj.py |
8.2 MIT Control
| Symptom | Recommendation |
|---|---|
| Joints too soft | Increase kp |
| Joint oscillation or jitter | Lower kp or increase kd |
| Sudden change when starting MIT motion | First call initialize_mit_gains() to smoothly transition Kp/Kd |
| Need completely no feedforward | Explicitly pass torque=0.0 or [0.0] * 7 |
| Sensitive to high-frequency control latency | Use send_mit_command() and maintain the frequency with an external loop |
8.3 IK and Trajectories
| Symptom | Recommendation |
|---|---|
| IK solving fails | Try a different method, or provide an initial joint angle closer to the target |
| Trajectory planning fails | Check the number of waypoints, joint limits, and waypoint units |
| Trajectory execution not smooth | Increase duration or lower the execution speed |
| Want to compare target and measured trajectories | Use 16_demo_joint_traj.py --track-joints --plot |
9. Troubleshooting
9.1 Cannot Connect to the Device
- Confirm that the Alicia-M is powered on and the USB cable is securely connected.
- Confirm that the serial port number is correct, e.g., Windows
COM37, Linux/dev/ttyACM0. - Confirm that the serial port is not occupied by another program.
- Linux users should confirm that they have been added to the
dialoutuser group; after the change, you need to log out and log back in. - First run
00_demo_read_version.pyto verify the minimal communication link.
9.2 Status Always Stays None
Background polling requires the device to be successfully connected and to receive the first batch of status frames. You can wait a few hundred milliseconds first, or check whether the firmware uploads status normally.
import time
state = None
for _ in range(20):
state = robot.get_robot_state("all")
if state is not None:
break
time.sleep(0.1)
print(state)
9.3 Mode Does Not Match Expectations
When connecting, control_mode=None means following the firmware's current mode. If the program must run in a specific mode, explicitly check and switch after creation.
if robot.control_mode.value != "pv":
robot.switch_mode("pv")
If you only read the version or status and do not want to sync the control mode on connection, you can set:
robot = alicia_m_sdk.create_robot(
port="COM37",
sync_control_mode=False,
)
10. Project Structure
alicia_m_sdk/
|-- api/ # Customer-facing unified API facade; the only business file is synria_robot_api.py
|-- _internal/ # Internal helper implementations, e.g., connection handshake
|-- execution/ # Internal joint control, trajectory execution, teleoperation
|-- hardware/ # Internal serial connection, protocol frames, device status polling
|-- integrations/ # Internal/advanced RoboCore kinematics and trajectory planning adapters
|-- types/ # Publicly exposable config, status, enums, exceptions
`-- utils/ # Internal tools and demo helpers
The layering relationship can be understood as:
demo code
|
v
SynriaRobotAPI unified entry
|
+-- _internal: connection handshake and internal coordination
+-- execution: motion control, gripper control, trajectory execution, teleoperation
+-- integrations: RoboCore kinematics and trajectory planning
+-- hardware: serial communication, protocol encoding/decoding, status polling
Regular development only needs to import the top-level package:
import alicia_m_sdk
robot = alicia_m_sdk.create_robot()
When you need type annotations or low-level capabilities, import types such as MitParams, JointState, and ControlMode as needed.
11. Development and Verification
For source development or before release, you can run the test, build, and package check commands in the SDK repository:
python -m pytest
python -m build
python -m twine check dist/*
On Windows, you can use the cleanup script to check or delete caches, build artifacts, and temporary files:
clean_sdk.bat /dry-run
clean_sdk.bat
By default, cleanup does not delete logs/ or the virtual environment; when you do need to include these directories, you can explicitly use clean_sdk.bat /logs or clean_sdk.bat /venv.
The SDK repository also contains extended documentation for maintenance and in-depth integration:
| Document | Purpose |
|---|---|
docs/API_MAINTENANCE.md | Maintenance interface descriptions |
docs/API_REFERENCE.md | API reference |
docs/ARCHITECTURE.md | SDK architecture description |
docs/PROTOCOL.md | Protocol encapsulation and underlying communication description |