CLI Reference
The CLI handles robot setup, server lifecycle, and diagnostics.
aiofranka start-server [--ip IP] [--no-home] Start the control server
aiofranka unlock [--ip IP] Unlock joints + activate FCI
aiofranka lock [--ip IP] Lock joints + deactivate FCI
aiofranka gravcomp [--ip IP] [--mode program] Move the robot by hand (freedrive)
aiofranka home [--ip IP] Move the robot to its home pose
aiofranka status [--ip IP] Show robot & server status
aiofranka stop [--ip IP] Stop a running server
aiofranka mode [--ip IP] [program|execute] View/change operating mode
aiofranka config [--ip IP] [--mass M] View/set end-effector config
aiofranka tool identify|load|list ... Identify, save and load tools
aiofranka camera calibrate|fit Locate a fixed camera relative to the robot
aiofranka selftest [--ip IP] [--force] Run safety self-tests
aiofranka log [-n LINES] [-f] View server logs
aiofranka gripper --open|--close Control the Robotiq gripper
aiofranka rt-benchmark [--duration SEC] Benchmark the 1 kHz control loop
unlock / lock
Unlock opens the brakes and activates FCI so the robot is ready for torque control.
It first recovers safety errors, runs the self-tests if they are overdue, and switches
from Programming back to Execution. Lock does the reverse. Credentials are prompted on first use and saved to ~/.aiofranka/config.json.
# Unlock before running your script
aiofranka unlock
# Lock when you're done
aiofranka lock
You can also do this from Python:
import aiofranka
aiofranka.unlock() # opens brakes + activates FCI
# ... run your control script ...
aiofranka.lock() # closes brakes + deactivates FCI
gravcomp
Runs gravity compensation mode in the foreground. The robot is freely movable by hand.
Press Ctrl+C to stop control; the joints remain unlocked with FCI active.
Run aiofranka lock when finished.
With --mode program, it switches the robot to Programming mode instead, as
aiofranka mode program does: the arm moves by hand only while the guiding button on the end
effector is held, and nothing keeps running. aiofranka unlock switches back for FCI.
aiofranka gravcomp # default: zero damping
aiofranka gravcomp --damping 2.0 # add velocity damping
aiofranka gravcomp --mode program # hand-guide with the guiding button instead
status
Shows robot state (joints locked/unlocked, FCI active/inactive, control token, self-test status, end-effector configuration) and server status if running.
aiofranka status
start-server
Runs the control server of the legacy server mode in the background (--foreground keeps
it in the terminal). It unlocks the robot (--no-unlock skips that),
moves it home (--no-home skips that) and runs the 1 kHz loop in C++
(NativeServerController). --python runs the legacy Python loop instead.
aiofranka start-server # the native loop
aiofranka start-server --python # the legacy Python loop
stop
Sends a shutdown signal to a running server process. The server deactivates FCI, locks joints, and releases the control token.
aiofranka stop
mode
View or change the operating mode. Execution is needed for FCI control.
Programming enables freedrive via the pilot interface button near the end-effector,
as Desk’s mode switch does: aiofranka mode program deactivates FCI, opens the brakes
if they are closed, and hands the control token back to Desk. aiofranka unlock
switches back to Execution by itself.
aiofranka mode # view current mode
aiofranka mode program # switch to Programming, to hand-guide the robot
aiofranka mode execute # switch back to Execution, for FCI
config
View or set the end-effector configuration (mass, center of mass, inertia,
flange-to-EE transform). Changes are applied via the Franka Desk API to the active
end-effector profile; to keep several tools by name, use aiofranka tool below.
aiofranka config # view current config
aiofranka config --mass 0.5 --com 0,0,0.03 # set mass + CoM
aiofranka config --translation 0,0,0.1 # set flange-to-EE offset
You can also set end-effector configuration from Python:
import aiofranka
aiofranka.unlock()
aiofranka.set_configuration(mass=0.5, com=[0, 0, 0.03])
aiofranka.lock()
tool
Identify the tool on the flange and keep it as an end-effector profile in Desk (Settings > End
Effector), the same profiles the web UI shows. The robot compensates the active profile, and
RobotInterface merges it into the MuJoCo model when it connects.
aiofranka tool identify gripper # move through 16 poses, save as profile "gripper", activate it
aiofranka tool load gripper # activate a profile
aiofranka tool unload # activate the built-in "No End Effector" profile
aiofranka tool list # list the profiles, marking the active one
aiofranka tool remove gripper # delete a profile
tool identify unlocks the robot like aiofranka home and plans the poses around the current
one, so move the arm to an open pose first. Describe the tool for the collision checks with
--tool-length and --tool-radius (default 0.2 m and 0.1 m), and the table with --floor
(default 0, the mounting plane; the robot keeps 5 cm from it). It shows the estimate and
asks before saving it, offering to edit the mass (in g) and the center of mass (in mm), e.g. to use
a scale reading; an existing profile keeps its tool center point and inertia. --no-load saves
it without activating it. See Payload Identification.
From Python:
import aiofranka
aiofranka.save_tool("gripper", mass=0.62, com=[0.0, 0.0, 0.045])
aiofranka.load_tool("gripper")
aiofranka.list_tools()
camera
Locate a fixed camera in the robot’s base frame with an AprilCube held on the flange. Print
aprilcube’s calibration cube
(cube.3mf),
mount it with its connector, start the camera with aiocamera start, and make the cube’s mass the
active Desk profile. It needs the camera extra: pip install "aiofranka[camera]".
aiofranka camera calibrate # move the arm by hand; captures and fits into camera_calibration/<date>/
aiofranka camera fit SESSION # fit a recorded session again
camera calibrate switches the robot to Programming mode like aiofranka mode program, with a
live view of the camera image in the terminal. Move the arm holding the guiding button on the end
effector, and let go: whenever it has rested for 0.7 s at a new pose, 5 cm or 10 deg from every view
so far, with the cube in view, it records the view and beeps. The joint positions come from Desk, as
its web UI gets them. Space captures anyway, u removes the last view, Enter fits and q quits
keeping the views. The fit writes calibration.json with T_base_camera, T_ee_cube, the
intrinsics and the reprojection errors on held-out views. The robot stays in Programming mode;
aiofranka unlock switches back.
selftest
Run the robot’s safety self-tests. The robot will lock joints during the test.
aiofranka selftest # run if due
aiofranka selftest --force # run even if not due
log
View recent server log entries from ~/.aiofranka/server.log.
aiofranka log # last 20 lines
aiofranka log -n 100 # last 100 lines
aiofranka log -f # follow (like tail -f)
rt-benchmark
Measures the 1 kHz loop on this machine. It holds the current pose in gravcomp, impedance and
OSC in turn, 10 s each (--duration), records every cycle and compares the modes. --mode
picks the modes; one mode prints its full report: the periods and their percentiles, the
response time from readOnce to writeOnce against a 300 us budget, skipped robot
states, dropped commands and a histogram. --python benchmarks the legacy Python loop
instead, with a breakdown per phase, and --all-combos compares its real-time settings.
aiofranka rt-benchmark # the native loop, every mode
aiofranka rt-benchmark --mode osc # one mode, its full report
aiofranka rt-benchmark --python # the legacy Python loop
Common Flags
Most commands accept these flags:
Flag |
Description |
|---|---|
|
Robot IP address (default: last used, or |
|
Franka Desk web UI username (default: saved or prompted) |
|
Franka Desk web UI password (default: saved or prompted) |
|
Web UI protocol (default: |