Dobot Robotics Lab — Open-Source Teaching Package for Magician & MG400
An open (Apache-2.0) robotics teaching package built for ME403 Introduction to Robotics: four progressive labs — forward kinematics, Jacobian/inverse kinematics, path planning, and image-based visual servoing — on a simulation-first stack that runs the Dobot Magician and MG400 with no hardware attached. 138 tests pass in 17 seconds on a laptop with no robot in the room.
1. Overview
dobot-robotics-lab is an open robotics teaching package that I maintain for ME403 — Introduction to Robotics at Sabancı University, released publicly under Apache-2.0.
It gives a student everything needed to go from a bare Python install to a working robot controller: four progressive lab exercises, helper APIs for two different Dobot arms, a simulation layer that stands in for the hardware, setup scripts, and the lab handouts. The design rule behind the whole package is simulation-first — a student writes and debugs their controller against a simulated arm, and only touches a real robot once the simulated behaviour is correct.
A pick-and-place cycle running with no hardware and no display: approach, descend, suction on, lift, transfer, release. Both stations sit at the same reach from the base, so the transfer is almost pure base rotation — the shoulder moves barely 3°. The arm motion and the suction state are real; the cube is drawn in, because the simulator tracks whether suction is on but does not model a payload.
Both arms are driven by the same student-facing API. Every figure on this page was generated by running the public package.
2. Why it exists
A robotics lab has a small number of arms and a large number of students. That scarcity usually decides the syllabus: exercises shrink to whatever can be demonstrated in a booked lab slot, and debugging happens with a queue of people waiting behind you.
The package removes the robot from the critical path:
- The simulator is the default, not the fallback. Every lab runs end-to-end with no hardware attached, so the interesting part — the kinematics, the planner, the control loop — can be written and debugged anywhere.
- Hardware motion is gated behind an explicit opt-in. Real motion requires
DOBOT_HARDWARE_CONFIRM=1; a student cannot drive a physical arm by accident while iterating. - The same code runs in both places. Switching from simulation to a real arm is an environment variable (
DOBOT_SIMULATION=0), not a rewrite — so what was verified in simulation is what runs on the robot.
3. The four labs
Each lab ships an interface.py runner that already works, plus a myCode.py scaffold where the actual algorithm is left blank. The student implements the theory; the surrounding plumbing — connection, bounds checking, plotting, playback — is not their problem.
| Lab | Topic | What the student implements |
|---|---|---|
| 01 | Forward kinematics | The FK chain, from joint angles to end-effector pose |
| 02 | Jacobian & inverse kinematics | The analytic Jacobian and a weighted Gauss–Newton IK solver |
| 03 | Path planning | Artificial potential fields and one probabilistic planner (PRM or RRT) |
| 04 | Visual servoing | An image-based visual servoing (IBVS) loop, with ChArUco camera calibration |
Labs run against either arm: DOBOT_ROBOT_TYPE=magician (the default) or mg400.
4. Two robots, one API
The package supports two arms that have almost nothing in common at the transport layer, and puts a shared session and motion API in front of both — with the genuine asymmetries (Magician-only tool offsets, MG400-only networking) documented per lab rather than papered over.
| Dobot Magician | Dobot MG400 | |
|---|---|---|
| Link | USB-serial | TCP/IP (Ethernet) |
| Reach | 320 mm | 440 mm |
| Notes | Suction, gripper, and bare-flange tool modes | Multi-robot station: several arms addressed by IP |
Because the MG400s are networked, the package ships a station IP map, so a room full of arms can be addressed by number rather than by hand-edited addresses.
The MG400 also hides a trap worth naming: its motion commands are body-frame, but the firmware expects an absolute elbow angle, J3_firmware = J2 + J3_body. Get that wrong and the arm is subtly, consistently off. The package converts explicitly (body_to_firmware_angles) and pins the convention down with its own test.
5. Simulation layer
What makes the sim-first rule credible rather than aspirational is that it is checked, on every push, by machines other than mine.
- 138 tests, 17 seconds, no hardware. The suite is organised into four tiers (
python3 scripts/validate.py --tier all) covering FK accuracy against analytic kinematics, Cartesian moves, workspace bounds, trajectory consistency, a collision guard, and the hardware safety gate itself. - CI runs it on six configurations. Ubuntu and Windows × Python 3.10, 3.11, 3.12, plus a dedicated job that installs MuJoCo and runs the full simulation tiers headless under OSMesa. The package does not just work on my machine — that is the entire point of publishing it.
- MuJoCo is the tested default; PyBullet is an optional second backend. The same robot and the same API run on either engine. In fairness: PyBullet passes locally but is not yet installed in CI, so it is a genuine second backend rather than an equally-guaranteed one.
- Real URDFs, prepared automatically. Vendored robot descriptions are fetched and compiled to a backend-ready model on first run — Collada meshes converted, collision geometry simplified, the parallelogram linkage constrained — then cached.
The Magician’s simulated joint convention was built to match what the firmware actually reports, so that a pose that is correct in simulation is correct on the bench. That claim rests on my own bench comparisons rather than on anything a reader can re-run — the package ships the parity tool (robot_parity_diagnostic.py) but no recorded hardware run, and I would rather say so than imply otherwise.
6. Quick start
No robot, no license, no account — a clean Python 3.10+ environment is enough:
git clone https://github.com/yunusdanabas/dobot-robotics-lab.git
cd dobot-robotics-lab
python3 scripts/bootstrap.py --simulation
Then run any lab. DOBOT_VIZ=0 keeps it fully headless — drop it to get the 3-D viewer:
cd labs/lab01_forward_kinematics
DOBOT_VIZ=0 python3 interface.py
Moving to real hardware is a change of environment, not of code. Motion on a physical arm is gated behind an explicit opt-in, and that gate has its own test:
DOBOT_SIMULATION=0 DOBOT_ROBOT_TYPE=magician DOBOT_HARDWARE_CONFIRM=1 python3 interface.py
7. Results from the package
Inverse kinematics (Lab 02)
The student derives the analytic Jacobian, then uses it to drive a weighted Gauss–Newton solver through the four corners of a square.
Left — the solver reaches the 1 mm tolerance at every corner in 14–18 iterations, with the clean geometric decay you expect from a damped Gauss–Newton step. Right — the analytic Jacobian's predicted end-effector motion plotted against what the arm actually did, over 20 random configurations: it lands on y = x, which is how a student knows their Jacobian is right before they ever trust it in a loop.
Path planning (Lab 03)
The planners run over procedurally generated maps of circular and rectangular obstacles, inflated by the tool radius. Below, all three solve the same cluttered map:
The same start/goal pair on the same map, solved by potential fields (242 mm), a probabilistic roadmap (224 mm), and an RRT (251 mm). The lesson is in the failure that isn't shown: plain potential fields gets stuck in a local minimum on this map and never reaches the goal — which is exactly why the lab makes students implement a probabilistic planner as well.
Visual servoing (Lab 04)
Lab 04 closes a loop through a camera: detect a target in the image, and drive the arm until the target sits at the optical centre — without ever computing where the target is in the world.
Image-based visual servoing in simulation: the marker centroid (left) is driven onto the optical centre, and the pixel error norm (right) decays from 178 px to under 8 px in 40 control steps.
The ChArUco board students print to calibrate the wrist-mounted webcam before servoing.
8. Resources
- GitHub repository — the package itself
- Release v2026.0 — first public release
- Licensed under Apache-2.0. Third-party robot descriptions and SDKs are credited in the repository’s
NOTICEfile.
Maintained alongside my teaching assistantship for ME403 — Introduction to Robotics, Sabancı University.