Complete pure-Python control library for Dobot Magician Lite (arm) and Magician GO (car) over DobotLink
Project description
dobotkit
Complete, pure-Python control for the Dobot Magician Lite robotic arm and the Dobot Magician GO mobile robot — one library, no DLLs, no native binaries.
dobotkit wraps both devices' DobotLink JSON-RPC bridge in clean,
type-hinted Python over websockets, so the same code runs on Windows, macOS,
and Linux with nothing more than pip install. DobotLink.exe must be
running for either device -- neither is driven over a raw serial port.
import dobotkit
with dobotkit.MagicianLite(port="auto") as arm:
arm.home()
arm.move_to(220, 0, 40, wait=True)
arm.suck(True)
Features
- Magician Lite arm over DobotLink — an ergonomic high-level
MagicianLiteAPI (home, move, pick-and-place, IO, sensors, end-effectors) wraps the arm'sMagician.*DobotLink JSON-RPC surface. No serial port, no serial-library runtime dependency. - Magician GO over DobotLink — a clean
MagicianGOcore: continuous drive (forward/strafe/spin + boundeddrive_for), ultrasonic/IMU/odometer/battery sensors, RGB LEDs, buzzer, alarms, andPreciseMoversensor-feedback motion (drive an exact distance / turn an exact angle). Its MagicBox peripherals read throughgo.sensors/go.io(ADC/DI by EIO pin, color/infrared/Seeed by Grove connector) on the same connection. - Pure Python — only
websocketsat runtime. No DLL, no vendored native code, no DobotDll/DobotRPC dependency. Cross-platform andpip-installable. - Fully type-hinted — every public symbol is typed and the package ships
py.typed, so editors andmypysee real types. - Safety-first — context-manager teardown for both devices (queue stop + disconnect on every exit path, including exceptions), and a sensor-feedback navigation layer for the GO with absolute wall-clock timeouts and pre-move clearance checks.
- Lazy device imports —
import dobotkitnever pulls inwebsockets; it is imported only when you first accessMagicianLiteorMagicianGO. - Ergonomic pydobot-flavoured API —
suck,grip,move_to, andmove_relativeread likepydobot.Dobot, so the everyday arm workflow (home -> move -> grab -> move -> release) needs no protocol knowledge.
Installation
pip install dobotkit
For development (editable install with the test/lint toolchain):
git clone https://github.com/mslopgk/dobotkit
cd dobotkit
pip install -e ".[dev]"
Requires Python ≥ 3.9. The only runtime dependency, websockets (used to
talk to DobotLink for both the arm and the GO), is installed automatically.
한국어 문서: 빠른 시작 quickstart-ko · GO API 치트시트 (LLM 프롬프트/RAG 접지용 1장 요약)
Quickstart — Magician Lite (arm)
The arm is not driven over a serial port: Python talks to the DobotLink
desktop service over a WebSocket (JSON-RPC 2.0), and DobotLink relays commands
to the arm over its COM port. DobotLink.exe must be running. Open a
MagicianLite as a context manager so the on-device command queue is stopped
and DobotLink is disconnected on every exit path, including exceptions.
import dobotkit
from dobotkit import PTPMode
# port="auto" picks the first port DobotLink reports; pass "COM3" to be explicit.
with dobotkit.MagicianLite(port="auto") as arm:
# Home first so absolute coordinates are trustworthy (blocks until done).
arm.home(wait=True)
# Set a gentle speed/acceleration (percentages; pydobot-compatible).
arm.set_speed(velocity=100, acceleration=100)
# Absolute straight-line move to (x, y, z, r) in mm/degrees; wait for finish.
arm.move_to(220, 0, 40, 0, mode=PTPMode.MOVL_XYZ, wait=True)
# Toggle the suction cup directly...
arm.suck(True)
arm.move_relative(dz=-20, wait=True)
arm.suck(False)
# ...or run the whole eight-step pick-and-place cycle as one queued program.
# Waypoints are (x, y, z) in mm; z_safe is the travel clearance between them.
arm.pick_and_place(
src=(200.0, 0.0, -30.0),
dst=(100.0, 150.0, -30.0),
z_safe=50.0,
settle_ms=300,
)
pose = arm.get_pose()
print(f"final pose: x={pose['x']:.1f} y={pose['y']:.1f} z={pose['z']:.1f}")
wait=True sends isWaitForFinish=true, so DobotLink blocks until the move
physically completes before returning (raising DobotTimeoutError only if the
per-call deadline elapses). Keep targets inside the workspace — a target that
drives a joint near its travel limit can fault.
If the arm accepts commands but does not move, its controller has an active alarm (motion is silently blocked while sensors/IO/effector still work). This is not reliably clearable from software — power-cycle the arm to clear it, then reconnect.
MagicBox peripherals (sensors, ADC/DI reads)
Every sensors.* read (adc, di, color, infrared, distance, temp,
light, rgb) and the read-only io.get_di / io.get_adc are routed
through the MagicBox. If it (or its device) is not connected, these calls
warn and return None rather than raising, so teaching code keeps
running:
reading = arm.sensors.color(port=0) # RuntimeWarning + None if no MagicBox
if reading is None:
print("색 센서를 읽지 못했습니다 — 매직박스/센서 연결 확인")
else:
print(reading)
v = arm.sensors.adc(24) # RuntimeWarning + None if no MagicBox
if v is None:
print("매직박스/센서 미연결")
Arm-native operations (motion, effector.suck / grip / servo, io.set_do
/ set_pwm / set_multiplexing) are unaffected and still raise on error, as
does a genuine connection error (DobotConnectionError, e.g. DobotLink is not
running).
Quickstart — Magician GO (mobile robot)
The GO is not driven directly: Python talks to the DobotLink desktop service over a WebSocket (JSON-RPC 2.0), and DobotLink relays commands to the car. DobotLink must be running.
Python --(WebSocket JSON-RPC)--> DobotLink --(COM/wireless)--> GO
from dobotkit import MagicianGO
from dobotkit.go.navigation import PreciseMover
# open() connects DobotLink + verifies the GO link with a battery read-back,
# and (as a context manager) stops the car + closes the socket on every exit.
with MagicianGO.open(port_name="COM5") as go:
try:
# Continuous velocity control is reliable: check clearance, then drive.
ok, info = go.clearance_ok(x=1, threshold=20)
if ok:
go.drive_for(x=20, seconds=1.0) # bounded forward pulse, auto-stops
finally:
go.emergency_stop() # fire-and-forget safety stop (never blocks)
# For precise motion use the sensor-feedback layer (continuous move + IMU/
# odometer feedback) — drive an exact distance or turn an exact angle.
mover = PreciseMover(go)
mover.goto_distance(300, speed=20) # ~300 mm forward, then stop
mover.turn_degrees(90, speed=20) # +90 deg (CCW), IMU-closed-loop
# MagicBox peripherals ride the same connection (guarded -> None if absent):
knob = go.sensors.adc(22) # potentiometer on EIO pin 22 (0..4095)
print("knob:", knob)
Safety
Robot hardware moves under power and can collide, pinch, or topple. dobotkit is
built to fail safe, but you must still operate it responsibly. The guidance below
comes from the Dobot Magician Lite and Magician GO operating notes.
Arm (Magician Lite)
- Power-on home. Always
home()after powering on so that absolute coordinates are trustworthy before issuingmove_to/pick_and_place. - Clearance checks. Verify the workspace is clear of obstacles, fingers, and fixtures along the planned path before commanding a move. Start with the illustrative coordinates lowered/slowed and tune to your setup.
- Wait timeouts, not silent success.
wait=TrueraisesDobotTimeoutErrorif the queued command never finishes, instead of returning as if it had. - Always disconnect. Use the
MagicianLitecontext manager (with ... as arm:) so the command queue is stopped and DobotLink is disconnected on every exit path — including exceptions.
GO (Magician GO)
- Verify the link. Use
go.connect()(it follows the connect handshake with a real battery read), because the raw handshake can report a false success. - Clearance before driving. Call
clearance_ok(...)for the intended direction of travel and only drive when it returnsTrue. - Timeouts everywhere. The
PreciseMovercontrol loops use absolute wall-clock timeouts (time.monotonic) so they can never spin forever, and every path ends inemergency_stop. - Always stop. Wrap motion in
try/finallyending ingo.emergency_stop()(a non-blocking notify, safe from afinallyblock or interrupt path even if the link is degraded); theMagicianGOcontext manager also stops on exit. - Precise motion = continuous move + feedback. For exact distances/turns use
PreciseMover(continuousmove()sampled against the odometer/IMU). The firmware's own built-in closed-loop commands were removed from this library because they can hang indefinitely on this chassis.
Feature coverage & verification
- Magician Lite arm via DobotLink. The ergonomic
MagicianLiteAPI (and itseffector/sensors/iogroups) wraps the arm'sMagician.*DobotLink JSON-RPC surface. DobotLink owns the wire protocol, struct packing, and command IDs -- there is no serial transport or wire-level code in this library. - Magician GO core, hardware-verified. The typed
MagicianGOclass wraps a clean, generally-used slice of theMagicianGO.*surface (drive, native sensors, RGB/buzzer, alarms) plusPreciseMoverfeedback motion. Turn direction is confirmed:r+= CCW (PreciseMover.turn_degrees(+90)verified). - GO MagicBox peripherals, hardware-verified (2026-07-16).
go.sensors/go.ioread the GO's MagicBox on theMagicBox.*namespace over the same connection. ADC/DI/DO/PWM address an EIO pin (1..26); color/infrared/Seeed address a Grove connector (1..6). Reads degrade toNone+ a warning when the MagicBox or sensor is absent. (Verified: potentiometer on Grove 4 = EIO 22.)
Project layout
dobotkit/
├── src/dobotkit/
│ ├── __init__.py # public exports (MagicianLite, MagicianGO, enums, exceptions)
│ ├── enums.py # PTPMode, JOGMode, GPIOType, EndEffectorType, ...
│ ├── exceptions.py # DobotError hierarchy
│ ├── link.py # DobotLinkClient (JSON-RPC over websockets) -- shared by arm + GO
│ ├── arm/ # Magician Lite arm, via DobotLink
│ │ ├── commands/ # ArmCommands: Magician.* RPC wrapper mixins
│ │ ├── groups.py # IO / Sensor / Effector facades
│ │ └── magicianlite.py # high-level MagicianLite API
│ └── go/ # Magician GO stack, via DobotLink
│ ├── geometry.py # pure helpers (yaw_delta, bearing, clamp_speed)
│ ├── groups.py # MagicBox sensor/IO facades (go.sensors / go.io)
│ ├── magiciango.py # high-level MagicianGO wrapper
│ └── navigation.py # PreciseMover (sensor-feedback motion)
├── examples/ # runnable demos:
│ # arm — arm_magicianlite
│ # GO — go_discover, go_teleop, go_magicbox_sensor
├── tests/ # mirror of src; FakeWebSocket / FakeClient doubles
└── docs/ # API reference
Public API
from dobotkit import MagicianLite, MagicianGO # device classes
from dobotkit import ( # enums
PTPMode, JOGMode, ContinuousPathMode, GPIOType,
EndEffectorType, ColorPort, LEDChannel,
)
from dobotkit import ( # exceptions
DobotError, DobotConnectionError, DobotTimeoutError,
DobotProtocolError, DobotAlarmError, DobotLinkError, DobotValueError,
)
from dobotkit.link import DobotLinkClient
from dobotkit.go.navigation import PreciseMover, NavigationAborted
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dobotkit-0.1.1.tar.gz.
File metadata
- Download URL: dobotkit-0.1.1.tar.gz
- Upload date:
- Size: 339.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e580248f255e93502fc3cbfcb506e172832d657ddf341ff306ed1e28a6477e4
|
|
| MD5 |
faf50a3b55c729be2aa6672172a695a0
|
|
| BLAKE2b-256 |
ed463a328cada6ec86555ceadd9e923e32fa3be6672c8dc4718a1151cb7975b9
|
File details
Details for the file dobotkit-0.1.1-py3-none-any.whl.
File metadata
- Download URL: dobotkit-0.1.1-py3-none-any.whl
- Upload date:
- Size: 43.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9466dc299dbaa51701b6b2a0d39c0551bb764e909f441ad87993ddccbcea6321
|
|
| MD5 |
7de815ef5bcecd34bd8cca0785c3399d
|
|
| BLAKE2b-256 |
8b9ef57795db85dde092eb647df97aa01d561d19251d4d1dd8c8f6d7ad1f0362
|