Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d52c478
doc: add a one-bot guide and route the docs nav to it
geonnave Jun 3, 2026
09ede53
readme: lead with the swarm quickstart, move one-bot and LH2 to guides
geonnave Jun 3, 2026
1f89955
dotbot: fetch and flash default to the latest swarmit release
geonnave Jun 3, 2026
eab6239
doc: fetch defaults to the latest release
geonnave Jun 3, 2026
774dad1
readme: drop the hardcoded firmware version (fetch defaults to latest)
geonnave Jun 3, 2026
2b4ad87
dotbot: clean up fetch output (package-manager style)
geonnave Jun 3, 2026
0a96e95
dotbot: add a bare-REST 'circle' demo (dotbot run demo circle)
geonnave Jun 3, 2026
6e0b93d
doc: add a simulator guide
geonnave Jun 3, 2026
40d6a47
readme: restructure onboarding around install, simulator, and swarm
geonnave Jun 3, 2026
859cd8d
dotbot: multi-source firmware fetch + ~/.dotbot/artifacts cache layout
geonnave Jun 3, 2026
670038d
dotbot/firmware: download fetch assets in parallel
geonnave Jun 3, 2026
1433a37
dotbot/cli: announce the active config file at startup
geonnave Jun 3, 2026
2a51c20
dotbot/firmware: retry transient download failures
geonnave Jun 3, 2026
1f170fc
dotbot/cli: summarize fetched firmware folders at the end
geonnave Jun 3, 2026
32ea774
dotbot/cli: centralize the default artifacts-cache path
geonnave Jun 3, 2026
8211263
dotbot/firmware: pin fetched firmware versions to pydotbot
geonnave Jun 3, 2026
7a2abea
doc: refresh firmware-cache location and pinned fetch
geonnave Jun 3, 2026
0e138eb
readme: point fetch + swarm-flash examples at the firmware cache
geonnave Jun 3, 2026
dd45ef8
dotbot/cli: default device role flash to the pinned swarmit version
geonnave Jun 3, 2026
406654d
dotbot/config: drop the unwired artifacts_dir key
geonnave Jun 3, 2026
6307f55
doc: align fetch/flash docs with the pinned default and drop artifact…
geonnave Jun 3, 2026
29f1e1a
readme: show concrete swarm-flash paths in the quickstart
geonnave Jun 3, 2026
dfb25ad
dotbot/firmware: make _short_path tolerate Windows cross-drive paths
geonnave Jun 3, 2026
4c9f223
dotbot/firmware: split release fetching out of flash.py into fetch.py
geonnave Jun 3, 2026
cdc15ea
doc: skip the 403-ing dotbots.org + segger.com links in linkcheck
geonnave Jun 3, 2026
a215bb1
doc: lead LH2 calibration with the OTA flow, split out the cabled guide
geonnave Jun 4, 2026
f93abc8
readme: add over-the-air LH2 calibration + rework Going further
geonnave Jun 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 72 additions & 139 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,13 @@

# PyDotBot

**The control plane for [DotBot](http://www.dotbots.org) swarms - build firmware,
flash a robot, and control a fleet over the air, from one bot to a thousand, all
from a single `dotbot` CLI and web UI.**
The control plane for the [DotBot](http://www.dotbots.org) - a small wireless
wheeled robot built to operate in large swarms, for research and education.

DotBots are small wireless wheeled robots built to operate in large swarms,
for research and education. Developed by the [AIO team](https://aio.inria.fr/) at
[Inria Paris](https://www.inria.fr/), and run routinely with ~100–200 bots,
with one 725-bot campaign.
PyDotBot allows you to flash a robot and control a whole fleet over the air,
from one bot to a thousand.

▶️ [Click to see a DotBot swarm in action](https://www.youtube.com/watch?v=pXGTLqafReU)

PyDotBot is the control plane in the middle: your code, the web UI, and users
talk to it, and it drives the swarm through a gateway.
[▶️ Click to see a DotBot swarm in action](https://www.youtube.com/watch?v=pXGTLqafReU)

```text
┌───────────┐ ┌────────────┐ ┌─────────┐
Expand All @@ -37,125 +31,53 @@ talk to it, and it drives the swarm through a gateway.
- 🧪 Try it all with **zero hardware** using the built-in simulator
- 🛠️ One `dotbot` CLI takes you from build → flash → run

## Try it now - no hardware
## Install

See the whole thing run with nothing but Python:
PyDotBot is available on [PyPi](https://pypi.org/project/pydotbot/), install it with:

```bash
pip install --pre pydotbot # using 'pre' while we are at release candidate
dotbot run simulator -w # opens the web UI at http://localhost:8000/PyDotBot/, driving a simulated swarm
```

Drive the simulated bots from the joystick + map - then script them from your own
code (below), or set up real hardware further down.

## Drive it from your own code

The controller - real or simulated - exposes a REST + WebSocket API, so you can
command the swarm in a few lines of Python (only extra dependency:
[`requests`](https://pypi.org/project/requests/)):

```python
import requests, time

BASE = "http://localhost:8000"
bot = requests.get(f"{BASE}/controller/dotbots").json()[0]["address"]

# roll in a circle for ~5 s - left_y and right_y are the two wheel speeds
for _ in range(50):
requests.put(f"{BASE}/controller/dotbots/{bot}/0/move_raw",
json={"left_x": 0, "left_y": 60, "right_x": 0, "right_y": 30})
time.sleep(0.1)
requests.put(f"{BASE}/controller/dotbots/{bot}/0/move_raw",
json={"left_x": 0, "left_y": 0, "right_x": 0, "right_y": 0})
pip install --pre pydotbot
```

The full surface - every endpoint, the live WebSocket stream, and CSV data
logging - is in the [REST / WebSocket reference][rest-doc] (or the
[MQTT bridge][mqtt-doc]). A higher-level Python SDK is planned; today you talk to
the controller over REST/WebSocket/MQTT.

The firmware for the DotBots can be found [here][dotbot-firmware-repo].
Then, check your installation with `dotbot --version` and learn what's possible with `dotbot --help`.

## Prerequisites (for real hardware)

Driving an already-provisioned swarm - or the simulator above - needs nothing but
Python. The tools below are only for building or cable-flashing firmware yourself.
Every command and flag is documented in the [CLI reference][cli-doc].

Software to install (as needed):
- Python ≥ 3.11 - ensure you also have [pip](https://pip.pypa.io/en/stable/) available in your PATH
- [nRF Command Line Tools](https://www.nordicsemi.com/Products/Development-tools/nRF-Command-Line-Tools) (`nrfjprog`), for commands such as `dotbot device flash`
- [SEGGER Embedded Studio](https://www.segger.com/products/development-tools/embedded-studio/), for commands such as `dotbot fw build`
## Try the simulator

Minimal hardware setup:
- DotBot v3, as well as a USB-C cable and a barrel-jack charger (2.5 mm, 6–18 V, 5/10 A)
- nRF5340-DK to use as gateway, as well as a micro-USB cable
See the whole thing run with nothing but Python!

## Install
The command below will run a simulated swarm, which you can observe in a web UI at http://localhost:8000/PyDotBot/ :

```bash
pip install --pre pydotbot # --pre while 0.29 is in pre-release
git clone --recurse-submodules --branch develop https://github.com/DotBots/DotBot-firmware.git
dotbot run simulator -w
```

## Usage

```
$ dotbot --help
Usage: dotbot [OPTIONS] COMMAND [ARGS]...

One CLI for the whole DotBot workflow: build and flash firmware, program and
control a single robot, and run experiments over the air across a swarm -
from one bot to a thousand.

Commands:
fw Firmware artifacts (no hardware): build / fetch / list / make.
device One connected device (cable/probe): flash an app/role, read info.
swarm The fleet over the air: status, start/stop, OTA flash, monitor.
run Host-side processes: controller, gateway, simulator, calibration, demos, teleop.
config Show the resolved config and where it came from; scaffold one with init.
```

Every command and flag is documented in the [CLI reference][cli-doc].

## Quickstart - one bot

Build and flash firmware for a single dotbot:
Drive the simulated bots from the UI, or run a bundled demo in a
second terminal:

```bash
# build the bare dotbot apps into ./artifacts/ (needs SEGGER Embedded Studio)
# two steps because the DotBot has two cores
dotbot fw artifacts --app dotbot
dotbot fw artifacts --app nrf5340_net --target nrf5340dk-net
# cable-flash it to the bot whose J-Link serial starts with 77
dotbot device flash dotbot -s 77 # app core
dotbot device flash nrf5340_net -b nrf5340dk-net -s 77 # network core
dotbot run demo circle # drive one bot in a circle (the simplest demo)
```

Now, build and flash the gateway to connect to a robot.
The gateway is a dev board (e.g. an nRF52840-DK) plugged into your
computer; it bridges the robot's radio to USB serial.
Learn how to script the swarm from your own code, run the richer examples, and more - all with
no hardware - in the [simulator guide][simulator-doc].

```bash
# build the gateway firmware for your DK board into ./artifacts/ (needs SEGGER Embedded Studio)
dotbot fw artifacts --app dotbot_gateway --target nrf52840dk
# cable-flash it to the DK whose J-Link serial starts with 10
dotbot device flash dotbot_gateway -b nrf52840dk -s 10
```
## Deploy a real swarm

With a gateway plugged into your computer, point the controller at it
and open the web UI:
The DotBot is made to operate as a swarm, here is how you can deploy it on real robots.

```bash
dotbot run controller --conn /dev/ttyACM0 -w # serial gateway; no swarm-id needed
```
### Prerequisites

More detail: building and flashing one board ([`fw`][fw-doc] / [`device`][device-doc])
and driving it from the web UI ([controller guide][controller-doc]).
Minimal hardware setup:
- DotBot v3, as well as a USB-C cable and a barrel-jack charger (2.5 mm, 6–18 V, 5/10 A)
- nRF5340-DK to use as gateway, as well as a micro-USB cable

## Quickstart - a swarm
Software to install (as needed):
- Python ≥ 3.11 - ensure you also have [pip](https://pip.pypa.io/en/stable/) available in your PATH
- [nRF Command Line Tools](https://www.nordicsemi.com/Products/Development-tools/nRF-Command-Line-Tools) (`nrfjprog`), for commands such as `dotbot device flash`

### setup the swarm
### Setup

To operate as a swarm, set your swarm connection config:

Expand All @@ -173,36 +95,38 @@ We also need a more powerful gateway firmware. Let's flash both - the network
id comes from your config:

```bash
dotbot fw fetch -f 0.8.0rc1 # pull the pre-compiled firmwares from a release
dotbot device flash-mari-gateway -s 10 -f 0.8.0rc1 # flash the gateway
dotbot device flash-swarmit-sandbox -s 77 -f 0.8.0rc1 # the sandbox firmware - do this on each dotbot
dotbot fw fetch # pull the pinned pre-compiled firmwares (swarmit + dotbot-firmware)
dotbot device flash-mari-gateway -s 10 # flash the gateway
dotbot device flash-swarmit-sandbox -s 77 # the sandbox firmware - do this on each dotbot
```

(`device flash-mari-gateway` / `flash-swarmit-sandbox` auto-fetch
the release into `./artifacts/` if it isn't already there.)
the firmware into `~/.dotbot/artifacts/` if it isn't already there.)

Now, run the gateway (the broker comes from your config):

```bash
dotbot run gateway -p /dev/cu.usbmodem0010500324491
```

### use the swarm
### Deploy and control

You can flash as many dotbots as you want, all at once! First, how about making them spinnnn 🔄 🔄

```bash
dotbot swarm flash ./artifacts/spin-sandbox-dotbot-v3.bin -ys # flash the whole fleet with a simple spinning app
dotbot swarm flash ~/.dotbot/artifacts/dotbot-firmware-1.22.0rc1/spin-sandbox-dotbot-v3.bin -ys # flash the whole fleet with a simple spinning app
```

(`dotbot swarm` reads the same `dotbot.toml` as the rest - pass `--conn` /
`--swarm-id` to override it for one run.)
`--swarm-id` to override it for one run. That path is the `dotbot-firmware`
release `dotbot fw fetch` cached - run `dotbot fw list` to see the exact paths
and versions on your machine.)

Then, flash another experiment:

```bash
dotbot swarm stop # ensure all robots are in bootloader
dotbot swarm flash ./artifacts/dotbot-sandbox-dotbot-v3.bin -ys # this firmware allows bots to be remote-controlled
dotbot swarm flash ~/.dotbot/artifacts/dotbot-firmware-1.22.0rc1/dotbot-sandbox-dotbot-v3.bin -ys # this firmware allows bots to be remote-controlled
```

Observe and control your swarm from a web interface:
Expand All @@ -214,36 +138,47 @@ dotbot run controller -w # will open a webpage at http://localhost:8000/PyDotBo
Full walkthrough of fleet operations - status, OTA flash, start/stop, monitor -
is in the [`swarm` reference][swarm-doc].

## Quickstart - Lighthouse 2 localization
### Calibrate positions (optional)

Give your robots a real-world `(x, y)` position. You'll need at least one
Lighthouse 2 base station and the calibration extra
(`pip install --pre 'pydotbot[calibrate]'`).
Give the bots real-world `(x, y)` with Lighthouse 2 - capture once from any bot
over the air, then push the result to the whole fleet (needs the `[calibrate]`
extra, below):

```bash
# 1. flash the capture firmware to a cabled dotbot and collect four corner points
dotbot device flash lh2_calibration -s 77
dotbot run lh2-calibration collect -p /dev/tty.usbmodem0007745943981 -d 200 # square of side 20 cm

# 2. push the resulting calibration to the fleet over the air
dotbot swarm stop # ensure all robots are in bootloader
dotbot swarm calibrate-lh2 ~/.dotbot/calibration-2026-05-26T14-00-36Z.toml
dotbot swarm stop # bots must be idle to capture
dotbot swarm lh2-calibration collect --device <addr> -d 500 # capture + solve + save
dotbot swarm lh2-calibration push ~/.dotbot/calibration-<UTC>.toml # apply to every bot
```

Your bots now report their `(x, y)` location. The full setup - arena sizing,
base-station placement, and troubleshooting - is in the
[LH2 calibration guide][lh2-doc].
`-d` is your reference square's side, in mm (one bot's capture calibrates the
whole arena). Full walkthrough - arena sizing and the cabled alternative - is in
the [LH2 calibration guide][lh2-doc].

## Going further

Full command reference and guides - running the controller + web UI, the four
CLI namespaces (`fw` / `device` / `swarm` / `run`), hardware, and LH2
calibration - are in the [documentation][doc-link].

Swarm orchestration is in the base install. Only LH2 calibration needs an extra:
- **Drive a single bot** end to end - build, flash, and control one DotBot:
the [one-bot guide][one-bot-doc].
- **Position tracking with Lighthouse 2** - give the fleet real-world `(x, y)`,
calibrated over the air: the [LH2 calibration guide][lh2-doc] (a cabled
alternative is covered there too).
- **The controller + web UI** - drive and visualize a swarm from the browser:
the [controller guide][controller-doc].
- **Build firmware from source** instead of `dotbot fw fetch` - needs
[SEGGER Embedded Studio](https://www.segger.com/products/development-tools/embedded-studio/)
and a DotBot-firmware checkout:
```bash
git clone --recurse-submodules --branch develop https://github.com/DotBots/DotBot-firmware.git
export DOTBOT_FIRMWARE_REPO=$(pwd)/DotBot-firmware
```
then `dotbot fw build` / `dotbot fw artifacts` (see [`fw`][fw-doc]).
- **Everything else** - the full `dotbot` CLI (`fw` / `device` / `swarm` / `run`
+ `config`), the REST/WS and MQTT surfaces, and hardware notes: the
[documentation][doc-link].

Most of `dotbot` is in the base install; only LH2 calibration needs an extra:

```bash
pip install --pre 'pydotbot[calibrate]' # opencv-python + textual (LH2 calibration)
pip install --pre 'pydotbot[calibrate]' # opencv (the LH2 homography solve)
```

Hitting a snag (e.g. the web UI not loading in Firefox)? See
Expand Down Expand Up @@ -271,14 +206,12 @@ See `LICENSE` in each component repository.
[license-link]: https://github.com/DotBots/pydotbot/blob/main/LICENSE.txt
[codecov-badge]: https://codecov.io/gh/DotBots/PyDotBot/branch/main/graph/badge.svg
[codecov-link]: https://codecov.io/gh/DotBots/PyDotBot
[dotbot-firmware-repo]: https://github.com/DotBots/DotBot-firmware
[cli-doc]: https://pydotbot.readthedocs.io/en/latest/cli/index.html
[fw-doc]: https://pydotbot.readthedocs.io/en/latest/cli/fw.html
[device-doc]: https://pydotbot.readthedocs.io/en/latest/cli/device.html
[swarm-doc]: https://pydotbot.readthedocs.io/en/latest/cli/swarm.html
[config-doc]: https://pydotbot.readthedocs.io/en/latest/reference/configuration.html
[simulator-doc]: https://pydotbot.readthedocs.io/en/latest/guides/simulator.html
[controller-doc]: https://pydotbot.readthedocs.io/en/latest/guides/controller.html
[one-bot-doc]: https://pydotbot.readthedocs.io/en/latest/guides/one-bot.html
[lh2-doc]: https://pydotbot.readthedocs.io/en/latest/guides/lh2-calibration.html
[troubleshooting-doc]: https://pydotbot.readthedocs.io/en/latest/reference/troubleshooting.html
[rest-doc]: https://pydotbot.readthedocs.io/en/latest/reference/rest.html
[mqtt-doc]: https://pydotbot.readthedocs.io/en/latest/reference/mqtt.html
9 changes: 5 additions & 4 deletions doc/cli/device.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ UART↔MQTT bridge process is a different thing - that's [`run gateway`](run.md)

## Flash an app

`flash` resolves `<app>` to `./artifacts/<app>-<board>.hex`, **building it if the
file isn't there**; an explicit `.hex`/`.bin` path is flashed as-is.
`flash` resolves `<app>` to a cached `<app>-<board>.hex` (under
`~/.dotbot/artifacts/`), **building it if the file isn't there**; an explicit
`.hex`/`.bin` path is flashed as-is.

```bash
export DOTBOT_FIRMWARE_REPO=$(pwd)/repos/DotBot-firmware
Expand Down Expand Up @@ -86,7 +87,7 @@ dotbot device flash nrf5340_net -b nrf5340dk-net -s 10

`flash-mari-gateway` and `flash-swarmit-sandbox` flash a **complete system firmware**
(both cores) and write the **network identity** in one shot. They auto-fetch the
named release into `./artifacts/` if it isn't cached.
named release into `~/.dotbot/artifacts/` if it isn't cached.

```bash
# nRF5340-DK → swarm gateway
Expand All @@ -99,7 +100,7 @@ dotbot device flash-swarmit-sandbox --swarm-id 0100 -f 0.8.0rc1 -s 77
| Flag | `flash-mari-gateway` | `flash-swarmit-sandbox` |
|---|---|---|
| `--swarm-id` | 16-bit hex swarm id (or from config) | 16-bit hex swarm id (or from config) |
| `-f, --fw-version` | release to flash (required) | release to flash (required) |
| `-f, --fw-version` | release to flash (default: the pinned swarmit version) | release to flash (default: the pinned swarmit version) |
| `-s, --sn-starting-digits` | J-Link serial prefix | J-Link serial prefix |
| `-l, --calibration` | - | optional LH2 calibration file to bake in |

Expand Down
Loading
Loading