Attending Pack EXPO 2026 CHICAGO? See our delta robot in action! Visit us at North Hall N-5584
Adeeb Robotics
Training Series 7 / 8
Adeeb Robot Controller

Commanding Axis Motion with the Adeeb Robot Controller API

A deep dive into the Adeeb Robot Controller's axis motion commands — absolute and relative moves, velocity and acceleration limits, and coordinated multi-axis motion in Python.

May 26, 2026 · 18:59

Watch on YouTube . The written walkthrough below covers the same material in detail.

This is the seventh video in our controller series. Earlier videos covered downloading and deploying the Adeeb Robotics libraries across operating systems; this one goes deeper into the motion control and EtherCAT APIs. The walkthrough uses Linux and the Adeeb Robot Controller, but the workflow is the same on every supported OS.

Launching the server and importing the API

Start the controller server for the Delta robot with sudo. Elevated privileges are required: without them the process cannot reach the Ethernet driver and you will hit confusing errors as the system blocks the changes it needs to make at the driver level.

With the server running, open a Python REPL from inside the Python scripts folder and import the helper module:

from arc import *

arc (ARC = Adeeb Robot Controller) is a convenience script shipped by Adeeb Robotics. It wraps the REST APIs and handles the request/poll mechanism for you. Each API in the manual is split into two parts: a POST that initiates the request and a GET that retrieves the response once the command completes. Because these commands take time to execute and the server cannot hang, you initiate with the POST and then poll for the result. The arc helpers do this for you — they fire the command, poll for the done flag and response, check the returned error codes, and print any errors. Import arc only after the server is running, since the helpers talk directly to the server. Importing also runs get_config, because some helpers — the autorun routines in particular — depend on configuration read from the server.

Initializing the controller

Initialize the controller before issuing any axis commands:

init_controller()

Initializing the controller initializes the network, initializes the axes, and brings EtherCAT into the OP state in one call. You could perform each of those steps individually, but the single call is more convenient. On success it scans the network, enters OP state, and reports the slaves it found.

If you skip initialization and issue an axis command anyway, you will get an invalid axis error because the axis does not yet exist in the system. init_controller is the longest-running command in the entire Python scripting library — the helper polls until the server reports completion, so the call only returns once the controller is fully initialized.

Physical versus virtual axes

When the axes initialize, the controller warns you if a configured axis cannot be found on the network. An axis is treated as physical when its slave index is set in the config. To make an axis virtual instead, comment out its slave index. Note that the controller does not yet support reinitializing after configuration changes — to apply a config edit you must quit the REPL, restart the server, and reinitialize. Support for in-place reinitialization is planned.

Servo on and servo off

Enable a single axis by passing its axis index. Axis commands have no default index, because most systems have more than one axis:

axis_servo_on(0)   # you should hear the motor hum
axis_servo_off(0)  # the hum stops

While an axis is servoed on you cannot back-drive it by hand — there is holding resistance at the joint. When it is off, the joint turns freely.

You can also enable the whole group at once. In this configuration axes 0, 1, 2, and 3 belong to one group whose type is a Delta robot:

group_servo_on()    # group index is optional
group_servo_on(0)   # or pass it explicitly

The group index is optional. APIs that act on parts, containers, conveyors, or groups treat their indices as optional, because the vast majority of deployments have exactly one of each. Supply an index only when you run multiple groups or conveyors.

There is also a _cycle variant, group_servo_on_cycle, which follows the cycling configuration. That path supports autorun — a way to run the robot without programming by configuring it to, for example, pick from a conveyor and drop into a container, or the reverse.

Error codes

Passing an index that does not exist returns a specific error code you can look up in the downloadable documentation:

  • Servoing on a non-existent group returns an invalid group index error.
  • Using a bad axis index — for example axis_servo_off(7) — returns invalid axis index (102).

Reading the current position

Before moving, read where the axis is. The default units are degrees:

axis_get_current_pos(0)   # e.g. 0.025 degrees, effectively zero

Absolute axis moves

Command an absolute move with axis_move. The first argument is the target position as a floating-point value; you must also supply the axis index. Positions are in degrees by default, and counterclockwise is positive:

axis_servo_on(0)
axis_move(90, 0)   # move axis 0 to +90 degrees (absolute)

If you omit the axis index the command reports that the index was not provided, and nothing moves.

Watch the gear ratio

In the demo, the first absolute move appeared to overshoot wildly because the axis gear ratio was set to 28. A 90-degree command is one quarter of a revolution, so the motor turned 28 ÷ 4 = 7 revolutions at the output. Setting the gear ratio to 1 makes commanded degrees match motor degrees. Because changing the gear ratio is a config edit, it requires quitting, restarting the server, and reinitializing.

Joint limits and recovery

This axis is configured as one of the joints of the Delta robot, so it has joint limits that protect the mechanism. If the axis starts outside its allowed range, the next move raises a motion alarm for exceeding the joint limits.

Recovery depends on your motor. With an incremental motor, cycle power to the servo drive: the position resets to zero. Then relaunch the REPL, re-import arc, reinitialize the controller, servo on, and command the move again:

from arc import *
init_controller()
axis_servo_on(0)
axis_move(90, 0)   # turns to +90 degrees

Velocity, acceleration, and the move profile

By default an axis runs its motion profile at 1% of the maximum possible value — velocity, acceleration, deceleration, and jerk are all capped at 1%. Raise the whole profile with axis_set_speed_percent, which scales the velocity and move-profile limits together:

axis_set_speed_percent(10, 0)   # axis 0 to 10% of maximum

At 10% the axis runs roughly ten times faster than the 1% default. With the faster profile set, subsequent moves complete noticeably sooner:

axis_move(0, 0)     # return to zero, now much faster
axis_move(-45, 0)   # -45 degrees is the negative joint limit here

Commanding -90 on this joint exceeds the position limit — only down to -45 is allowed — so the controller rejects it. Moving to -45 succeeds.

Command reference

CommandArgumentsPurpose
init_controller()Initialize network and axes, enter EtherCAT OP state
axis_servo_on(idx)axis indexEnable a single axis
axis_servo_off(idx)axis indexDisable a single axis
group_servo_on(idx?)group index (optional)Enable a group; index defaults to the only group
group_servo_on_cycle()Enable group following the cycling/autorun config
axis_get_current_pos(idx)axis indexRead current position (degrees)
axis_move(pos, idx)target degrees, axis indexAbsolute move; CCW positive
axis_set_speed_percent(pct, idx)percent, axis indexScale velocity and move-profile limits

Indices for groups, parts, containers, and conveyors are optional and default to the single configured instance; axis indices are always required. Out-of-range indices return invalid-index error codes (for example, invalid axis index 102), and moves beyond a configured joint range raise a motion alarm.

Next steps

You have seen how to bring the controller up, servo axes on and off individually or as a group, read positions, command absolute moves, and tune the velocity and acceleration profile. The next video goes further into coordinated group motion.

Next in the Training Series

Part 8 of 8

Automating Pick-and-Place with the Autorun Feature