A cable-driven robot that paints walls. Two belts, two steppers, one hanging tool gondola — a "polargraph" vertical plotter scaled up from pen-on-paper to paint-on-wall.
In 2019 I spent a semester in an Aalborg startup incubator doing business planning and market research for a wall-painting robot. The market said yes; the technology of the day (and my runway) said not yet, and the project ended as a folder of spreadsheets.
It's 2026 and the parts bin has changed: closed-loop-silent stepper drivers cost six euros, an ESP32 outruns the motion controllers we priced back then, and a vision model can segment a window out of a phone photo. So this is the same idea, revived as an open-source build — in public, weekends-paced, honest about what works and what doesn't.
This is my hands-on hardware track. Its sibling project, ballbot-modern, is the simulation/learning track (my MSc thesis ballbot, resurrected in a modern stack).
Flat mode — uniform coverage. Paint a wall region with even coverage (roller or spray): boustrophedon passes with configurable tool width, edge handling, and rectangular keep-out zones for windows, outlets, and the parts of the wall you like as they are.
Mural mode — pictures. High-resolution landscape/picture painting via airbrush halftoning: image → tone mapping → error-diffusion dithering → an ordered dot/stroke plan the gondola can execute.
Further out (and honestly caveated): wall sanding and skim-coat application. Contact-force tasks don't suit a hanging cable gondola — it can't push against the wall — so that track likely needs a different machine. See ROADMAP.md for the physics and the options; the short version is that companies like Canvas Construction already do robotic drywall finishing commercially, which validates the market even though it rules out this rig.
anchor A anchor B
[stepper + GT2 pulley]···················[stepper + GT2 pulley]
\ /
\ belt L1 / belt L2
\ /
\ /
+——————————[ gondola ]——————————+
| tool: pen → airbrush → spray |
| servo pen-lift / spray valve |
+———————————————————————————————+
|
v +y (down)
laptop: Python planner (this repo)
└── streams moves over USB/Wi-Fi ──▶ ESP32-S3 firmware (step gen, TMC2209)
camera (later): wall photo ──▶ segmentation ──▶ keep-out zones
Two anchor points at the top of the wall each carry a stepper with a GT2
belt; the belts meet at a hanging tool gondola. Belt lengths (L1, L2) are the
joint space; the planner does everything in wall coordinates and the
kinematics module converts. Gravity is the third actuator: it keeps both
belts in tension — inside a limited region. Where the tensions leave the
allowed band, the robot cannot go; wallbot.kinematics computes that region
before any hardware exists to discover it the hard way.
The Python package is the planner and analysis stack:
| Module | What it does |
|---|---|
wallbot.kinematics |
FK/IK, Jacobian, static belt tensions, workspace feasibility maps, belt-sag error estimates |
wallbot.pathplan |
flat-mode boustrophedon coverage with keep-outs; mural-mode dither + dot-ordering pipeline |
wallbot.demo |
end-to-end dry run on a 4 × 2.5 m wall |
Honest inventory. Nothing physical exists yet. This is a scaffold with working math.
| Exists | Does not exist |
|---|---|
| Polargraph kinematics + statics, tested to 1e-9 round-trip | Any hardware (first order: see hardware/BOM.md) |
| Tension-feasibility workspace analysis | ESP32 firmware |
| Flat-mode coverage planner with keep-out zones | Airbrush/spray tooling |
| Mural-mode halftoning pipeline (dither → ordered dots) | Camera/vision wall mapping |
| Test suite (19 tests) and a runnable demo | Any painted wall |
What the day-0 planner computes for a 4.0 × 2.5 m wall (run it yourself,
python -m wallbot.demo):
usable workspace: 85.2% of the wall (top 25 cm strip needs anchors mounted higher)
flat mode: 3.50 x 2.05 m region, 1 window keep-out -> 45.3 m of passes,
100.0% coverage of the free area, ~16 min at 50 mm/s
mural mode: 1.20 x 0.77 m synthetic landscape at 12 mm dot pitch -> 3625 dots,
mean brightness preserved 0.435 -> 0.434, ~29 min estimated
pip install -e ".[dev,viz]"
pytest # 19 tests
python -m wallbot.demo # prints stats, saves out/demo.pngPython ≥ 3.10, numpy required; pillow for loading your own mural images; matplotlib only for the demo plot (both import-guarded).
Full detail with definitions of done in ROADMAP.md.
| Phase | What | Rough effort |
|---|---|---|
| P0 | Simulation & kinematics on paper targets (this scaffold) | done + ongoing |
| P1 | Pen/marker plotter on a ~1 × 1 m foam board | ~3–4 weekends |
| P2 | Airbrush gondola, grayscale halftone murals | ~4–6 weekends |
| P3 | Flat mode with roller/spray and keep-out zones | ~3–5 weekends |
| P4 | Perception: camera wall-mapping, CV keep-out generation | ~4–6 weekends |
| P5 | Scale-up to a full wall + natural-language job specs | open-ended |
| — | Sanding & skim-coat research track (different machine; see roadmap) | unscheduled |
The modern-AI angle arrives in P4/P5: a camera + vision model maps the wall (segment windows/outlets/edges → keep-out zones), job specs move to natural language ("paint everything except the door wall in RAL 9010"), and mural mode becomes an image-to-robot-action pipeline end to end.
This repo is the project log, not a product. Progress lands here as it happens — including the failed experiments, because a hanging gondola on five-metre belts will produce plenty. Issues, ideas, and prior-art pointers welcome. The hobby ancestors of this build — Polargraph and the many vertical plotters since — did the pen-scale proving; wallbot's bet is that paint delivery, coverage guarantees, and perception are what turn a plotter into a tool.
MIT © 2026 Victor Borja