Skip to main content

Synria Follower Arm Python SDK v1.1.1

Version Compatibility

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

What the SDK Can Do
  • Unified control entry: create_robot() creates a SynriaRobotAPI instance, 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 Windows COM37 or 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
Package Name and Import Name

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:

SystemCheck Method
WindowsOpen Device Manager and view the COM ports
Linuxls -l /dev/ttyUSB* /dev/ttyACM*
macOSls /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:

ParameterDescription
target_joints6 joint target angles; uses degrees when joint_format="deg", radians when "rad"
speedJoint motion speed parameter; the larger the value, the faster the motion
wait_for_completionWhether to wait until motion arrives before returning
gripper_valueOptional gripper target value, range 0~1000
gripper_speedGripper 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:

ParameterDescription
kpPosition loop gain; can pass a scalar, a 6-joint list, or a 7-motor list
kdVelocity loop gain; can pass a scalar, a 6-joint list, or a 7-motor list
torqueFeedforward torque, in N·m; can pass a scalar, a 6-joint list, or a 7-motor list
vel_refTarget velocity, in rad/s; can pass a scalar, a 6-joint list, or a 7-motor list
use_interpolationWhether to use linear trajectory interpolation in MIT mode
Zero Values Are Not Overridden by Defaults

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_typeReturned ContentNotes
"joint"list[float]6 joint angles, in rad
"joint_gripper"dictangles and gripper
"velocity"list[float] or NoneJoint velocities, in rad/s
"torque"list[float] or NoneJoint torques, in N·m
"linear_vels"list[float] or NoneInterpolation velocity, requires extended polling
"temperatures"list[float] or NoneCoil temperature, requires extended polling
"all"JointState or NoneComplete status object
"version"VersionInfo or NoneFirmware version, hardware version, etc.
"status"RobotStatus or NoneOperating status
"control_mode"list[dict] or NoneOne-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:

ParameterRecommended ValueDescription
port"" or the actual serial portAuto-discover or manually specify the serial port
version"auto"Automatically identify the hardware/model version; can be explicitly specified when using kinematics offline
control_aimNoneUsually the Alicia-M acts as a follower; teleoperation scripts explicitly pass "follower"
control_modeNoneLet the SDK follow the device's current mode; pass "pv" or "mit" when a fixed mode is needed
sync_control_modeTrueCan 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_pollingFalseOnly 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,
)
ParameterDescription
target_joints6 joint target angles; None means do not change the joints
gripper_valueGripper target value 0~1000; None means do not change the gripper
joint_format"deg" or "rad"
speedJoint motion speed parameter
gripper_speedGripper motion speed parameter
wait_for_completionWhether to wait for arrival at the target
use_interpolationWhether to use linear interpolation in MIT mode
kp / kdMIT impedance gains
torque / vel_refMIT 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
Writing User Settings

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:

InterfacePurpose
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:

  1. Run 00_demo_read_version.py to confirm that the SDK can connect to the device and read the firmware version.
  2. Run 02_demo_read_status.py or 03_demo_read_states.py to confirm that the operating status, control mode, joint angles, and gripper value are read normally.
  3. Run 06_demo_move_gripper.py or 07_demo_move_joint.py to 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.FilePurpose
0000_demo_read_version.pyRead firmware version, hardware version, and device information; recommended as the first step for connection verification
0101_demo_diagnostic.pyRun device self-test to check whether communication and device response are normal
0202_demo_read_status.pyRead control mode and operating status
0303_demo_read_states.pyLoop-print joint angles, gripper, velocity, torque, and extended status
0404_demo_switch_mode.pySwitch PV / MIT control mode
0505_demo_disable_enable.pyDemonstrate 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.FilePurpose
0606_demo_move_gripper.pyControl gripper opening/closing independently
0707_demo_move_joint.pyPV mode joint motion
0808_demo_move_full_arm.pyPV mode coordinated joint + gripper motion
0909_demo_move_joint_mit.pyMIT mode joint motion
1010_demo_move_full_arm_mit.pyMIT 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.FilePurpose
1111_demo_forward_kinematics.pyRead the current joint angles and compute the end-effector pose
1212_demo_inverse_kinematics.pyDemonstrate IK solving and optional execution
1616_demo_joint_traj.pyJoint-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.FilePurpose
1313_demo_reset_zero.pySet the current pose as the zero position
1414_demo_teleop_mapped.pyAlicia-D to Alicia-M URDF limit mapping teleoperation
1515_demo_gripper_params.pyRead and write gripper gripping parameters
1717_demo_mit_torque_switch.pyMIT mode torque switch test
1818_demo_user_settings.pyRead 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:

ParameterDefaultDescription
--modemitFollower control mode, options pv / mit
--leader-portCOM63Alicia-D teaching arm serial port
--port / --follower-portCOM51Alicia-M follower arm serial port
--follower-versionv1_1Alicia-M model version
--frequency100.0Control loop frequency, in Hz
--speed200.0Follower motion speed parameter
--interpolationOffEnable linear interpolation in MIT mode
--homeOffMove the Follower to zero before teleoperation
--verboseOffPrint mapping status
Teleoperation Safety

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

SymptomRecommendation
Motion too fastLower speed or gripper_speed
Still a noticeable error after arrivalCheck whether the target angle unit matches joint_format
Gripper action direction does not match expectationsConfirm that the gripper type configuration matches the actual hardware
Multi-segment motion not smooth enoughUse plan_joint_trajectory() or 16_demo_joint_traj.py

8.2 MIT Control

SymptomRecommendation
Joints too softIncrease kp
Joint oscillation or jitterLower kp or increase kd
Sudden change when starting MIT motionFirst call initialize_mit_gains() to smoothly transition Kp/Kd
Need completely no feedforwardExplicitly pass torque=0.0 or [0.0] * 7
Sensitive to high-frequency control latencyUse send_mit_command() and maintain the frequency with an external loop

8.3 IK and Trajectories

SymptomRecommendation
IK solving failsTry a different method, or provide an initial joint angle closer to the target
Trajectory planning failsCheck the number of waypoints, joint limits, and waypoint units
Trajectory execution not smoothIncrease duration or lower the execution speed
Want to compare target and measured trajectoriesUse 16_demo_joint_traj.py --track-joints --plot

9. Troubleshooting

9.1 Cannot Connect to the Device

Connection Failure
  • 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 dialout user group; after the change, you need to log out and log back in.
  • First run 00_demo_read_version.py to 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:

DocumentPurpose
docs/API_MAINTENANCE.mdMaintenance interface descriptions
docs/API_REFERENCE.mdAPI reference
docs/ARCHITECTURE.mdSDK architecture description
docs/PROTOCOL.mdProtocol encapsulation and underlying communication description