Skip to content

dotbot/site: add walls and obstacles to a site pack - #328

Open
geonnave wants to merge 63 commits into
DotBots:mainfrom
geonnave:site-editor-p3
Open

geonnave wants to merge 63 commits into
DotBots:mainfrom
geonnave:site-editor-p3

Conversation

@geonnave

@geonnave geonnave commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #327 (editor comfort), on #326, #315 and the LH2 stack to #343. Merges after them; until then the diff also carries their commits.

Walls and obstacles become part of a site pack, and every reader learns them in this PR, so the editor never draws something nothing else reads:

[[walls]]          # a polyline robots cannot cross, frame mm
name = "divider"   # optional
points = [[1500, 2500], [3000, 2500]]

[[obstacles]]      # a polygon robots cannot enter; the last point joins the first
name = "pillar"
points = [[3000, 1800], [3300, 1800], [3300, 2100], [3000, 2100]]
  • Schema: SiteSection.walls (2 points or more) and .obstacles (3 or more), strict like the rest. Site.walls / .obstacles.
  • Controller: GET /controller/site (and the qrkey site reply) carries walls and obstacles.
  • Console: the map draws walls as solid lines and obstacles as filled polygons, under the robots.
  • Simulator: a robot's body is taken as a disc (the v3's 95 mm envelope) round its outline's centre, 24.5 mm ahead of the axle. A tick that would put the disc across a wall or an obstacle's edge, or inside an obstacle, is not taken: the body stays where it was with its wheels stalled, so the encoders count nothing and the firmware's estimate stays with the truth. A body already in contact may move off or along the barrier, never deeper into it or with its centre across it, and one placed inside an obstacle may drive out. Only robots whose wheels moved are checked, and each against the barriers whose boxes it can reach. So a robot driven at a wall stops at it and its waypoint batch fails, as on the floor. (A first version let the wheels slip, and the reported pose then drifted through the wall on encoder counts while the body stayed put.)
  • Editor: Wall (W) and Obstacle (O) tools: click the points, double-click or Enter to finish, Esc to cancel, snapped like areas. With Select, a barrier is moved whole or point by point, nudged with the arrows, and edited in the inspector (name, points as x, y lines, comment), with Undo. Checks: too few points (error), a point outside the extent (warning). The patcher writes the arrays of tables in place: an unchanged entry and its comment are left byte for byte, a moved point changes that number only, a new entry is appended after a blank line, a deleted one goes with its comment.

Also: the scenario harness takes a site.

Plan: rendered copy https://claude.ai/artifact/LHUXjhx1nMWifC2oGRBayt, source https://github.com/DotBots/dotbot-workspace/blob/main/plans/site-editor/plan.html (both internal).

Walls or obstacles written inline (walls = [{...}]) are refused rather than replaced on the first save, deleting an entry keeps the comments heading the others, and a body that leaves out walls or obstacles leaves the file's table alone.

Validation. pytest: walls and obstacles read and refused (too few points, unknown key), served and round-tripped through the REST model; the blocking test on a disc against a segment and inside a polygon; a robot driven at a wall stops within a millimetre of contact while one past the wall's end drives on; a robot in contact backs off; a scenario (stepped controller and simulator) where a waypoint behind a wall is not reached and the site route serves the wall; the patcher's byte-identical round trip of a walled file, a moved point, an add and a delete keeping the other comments, the first and last array of tables, too few points refused. vitest: the map draws a wall and an obstacle; the editor draws a wall point by point and saves it as a new entry next to an unchanged obstacle, edits an obstacle's points as text and deletes it; point parsing, moving and the double-click dedup. npm run lint, typecheck and build; pre-commit run --all-files; full pytest 1832 passed, vitest 869 passed; also a robot placed against or across a wall cannot drive through it, one inside an obstacle drives out, idle robots are not checked, Backspace while drawing keeps the selection, scenarios 15 passed.

By hand, headless: dotbot site new walled, a wall and an obstacle added through the editor's REST save; dotbot run simulator --site walled --robots 4; two robots sent across the wall stop at it (batch FAILED) while a third reaches its goal; /console in headless Chrome draws the wall, the obstacle and the stopped robots; the editor draws, selects and draws a new obstacle in Chrome.

+ - Files
#315, the LH2 stack to #343, #326 and #327, carried underneath (merge separately) +9952 -390 89
This PR, tests +460 -4 9
This PR, source +848 -26 16
This PR's files + -
dotbot/console-web/src/siteEditor/Canvas.tsx +165 -6
dotbot/sim/barriers.py +170 -0
dotbot/tests/test_site_barriers.py +170 -0
dotbot/console-web/src/siteEditor/Inspector.tsx +134 -3
dotbot/tests/test_site_toml.py +132 -1
dotbot/site_toml.py +101 -1
dotbot/console-web/src/siteEditor/SiteEditor.tsx +63 -8
dotbot/console-web/src/siteEditor/siteEditor.test.tsx +57 -1
dotbot/console-web/src/barrierLayer.test.tsx +50 -0
dotbot/console-web/src/siteEditor/edit.ts +46 -1
dotbot/console-web/src/siteEditor/edit.test.ts +30 -0
14 small files: dotbot/site.py, MapView.tsx, dotbot/models.py, plant.py, dotbot/config.py, dotbot/site_editor.py, types.ts, test_site_editor.py, api.ts, types.ts, scenario_harness.py, test_server.py, dotbot/dotbot_simulator.py, test_qrkey_app.py +190 -9
Total, 25 files +1308 -30

Docs (the site pack format page) follow after review.

@codecov

codecov Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.73380% with 236 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.41%. Comparing base (ddc43f7) to head (0b67064).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
dotbot/console-web/src/siteEditor/Canvas.tsx 82.08% 105 Missing ⚠️
dotbot/console-web/src/siteEditor/SiteEditor.tsx 87.58% 72 Missing ⚠️
dotbot/console-web/src/siteEditor/api.ts 82.95% 15 Missing ⚠️
dotbot/console-web/src/siteEditor/Inspector.tsx 97.24% 10 Missing ⚠️
dotbot/console-web/src/siteEditor/main.tsx 0.00% 8 Missing and 1 partial ⚠️
dotbot/cli/swarm_lh2.py 91.80% 5 Missing ⚠️
dotbot/console-web/src/siteEditor/edit.ts 97.28% 5 Missing ⚠️
dotbot/tests/lh2_multi_fixture.py 94.80% 4 Missing ⚠️
dotbot/console-web/dev/fake_swarmit_server.py 0.00% 3 Missing ⚠️
...ot/console-web/src/siteEditor/CalibrationPanel.tsx 97.76% 3 Missing ⚠️
... and 4 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #328      +/-   ##
==========================================
+ Coverage   88.21%   88.41%   +0.20%     
==========================================
  Files         227      239      +12     
  Lines       36147    38887    +2740     
  Branches     2324     2832     +508     
==========================================
+ Hits        31886    34381    +2495     
- Misses       4257     4501     +244     
- Partials        4        5       +1     
Flag Coverage Δ
console 83.22% <89.74%> (+1.22%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
dotbot/cli/main.py 95.83% <ø> (ø)
dotbot/cli/site_cmd.py 91.54% <ø> (-0.04%) ⬇️
dotbot/config.py 98.59% <ø> (-0.29%) ⬇️
dotbot/console-web/src/BotMarker.tsx 100.00% <100.00%> (ø)
dotbot/console-web/src/GridView.tsx 88.20% <100.00%> (-0.22%) ⬇️
dotbot/console-web/src/ListView.tsx 88.78% <100.00%> (+0.64%) ⬆️
dotbot/console-web/src/LocalizationPanel.tsx 86.09% <100.00%> (ø)
dotbot/console-web/src/MapView.tsx 97.59% <100.00%> (+0.04%) ⬆️
dotbot/console-web/src/botFacts.ts 98.10% <100.00%> (+0.66%) ⬆️
dotbot/console-web/src/heldWaypoints.ts 100.00% <100.00%> (ø)
... and 44 more

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

AI-assisted: Claude Opus 5.5
AI-assisted: Claude Opus 5.5
… page

Any web page in the browser can send requests to 127.0.0.1 with a valid
Host header, and behind a permissive CORS policy read the replies, so the
Host check alone let it save site.toml; a server bound beyond loopback
took any Host. The peer address, Origin and Sec-Fetch-Site are checked.

AI-assisted: Claude Opus 5.5
…ng tables

A patched file is read back and must give the model that was sent, so a
layout the patcher does not follow is refused rather than written.

AI-assisted: Claude Opus 5.5
Breaking: schema 3 calibration files are refused, so a calibration is
collected again. swarmit's own calibration reader still expects schema 3
and needs its matching change before the dashboard reads these files.

AI-assisted: Claude Opus 5.5
…tangle

Breaking, cross-repo: the messages and the config page (magic SWRP, 872
bytes) only match a swarmit bootloader and net core that store stations
by mask, and swarmit's Python must accept mask messages before it relays
them. Robots below device info 4 are refused with a reflash.

AI-assisted: Claude Opus 5.5
Breaking wire change, landing with DotBot-libs' 16-bit calibrated field:
every advertisement field after the mask moves by one byte and the
vendored dotbot_control.wasm is rebuilt at ABI 3 from that change. With
the one-byte mask, a calibration naming station 8 or above read every
sandbox robot as missing it and resent homographies on each advert.

AI-assisted: Claude Opus 5.5
… a file

A placement's id comes from its stations, not its tag or anchor, so the
same move saved twice, or a move into the source's own site, landed on an
existing path; save_placed keeps that file and refuses the source's id.

AI-assisted: Claude Opus 5.5
…leave omitted tables

AI-assisted: Claude Opus 5.5

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant