EmberOS firmware
EmberOS is the robot half of Ember: a firmware image built from WireOS, which is itself a rebuild of Anki’s own robot software from the sources Digital Dream Labs released.
Installing it is optional. Ember’s server and brain work with a robot on stock WireOS; the firmware exists because some things — detectors that stay on without a client holding behaviour control, a thermal daemon, styleable eyes — cannot be done from a server at all.
What it changes over stock
Section titled “What it changes over stock”A boot animation of its own
Section titled “A boot animation of its own”The robot’s boot animation is generated rather than drawn: a glowing ember with rising sparks that settles into the name, written out as raw 184×96 RGB565 frames at 24 frames a second — the format the robot’s boot animation process memory-maps. The generator lives with the firmware files, so changing the animation is running a script, not editing an asset.
It points at your server, not at anyone else’s
Section titled “It points at your server, not at anyone else’s”The robot’s cloud client finds its server by mDNS name rather than by a hard-coded address, and the certificate that server presents is embedded in the image and trusted, so a robot pairs without needing an override file dropped onto him first. The updater’s base URL, the fault-code screen and the rescue screen all point at your own server too. There are no third-party addresses left in the image, and the info screen says EmberOS.
Calm docked idle
Section titled “Calm docked idle”Out of the box, a docked robot makes a small movement about every thirty seconds, forever. EmberOS stretches that curve so a settled robot moves about every thirty minutes instead. Eye contact and his reaction to movement are untouched — he still looks up when you walk past.
The same change is available from the server as the calm behaviour preset, applied over SSH with no rebuild, if you would rather not reflash.
Styleable eyes
Section titled “Styleable eyes”The animation process reads an eye-style file from the robot and applies it after the usual interpolation: scale, offset, angle, corner radii, lid offset and bend, and spacing. It re-reads the file when its modification time changes, roughly once a second, so the dashboard’s eye builder updates live. The animation loader also reads a directory of the owner’s own clips.
Always-on detectors
Section titled “Always-on detectors”On stock firmware, a detector a server asks for is refused unless the server holds behaviour control, and is dropped the moment control is released. EmberOS adds a file on the robot that switches detectors on independently of any client: faces, motion, markers, and the newer ones below. That is the mission applied to the robot — the detections flow, and whatever wants them subscribes.
It also exposes detections that never left the robot before — pets, laser points, illumination and the neural-net person and hand detections — through the robot’s external protocol, converted the same way motion already was. See Vision.
Cliff stop under behaviour control
Section titled “Cliff stop under behaviour control”Taking behaviour control over the robot’s SDK used to switch his cliff sensors off. That is not a theory: it is how this robot drove off a desk. Later builds keep the reflex armed while a client holds control, and report it firing as an event so the server knows why an action stopped and whether he reversed off the edge.
Until such a build is installed, Ember’s social engine refuses every step that turns his wheels, whatever the settings say.
A thermal daemon
Section titled “A thermal daemon”WireOS defaults the robot to a 1.27 GHz CPU ceiling against a stock 533 MHz, and this robot reached 87 °C there. Meanwhile the platform’s own thermal throttling is disabled at boot by the vendor’s init script.
EmberOS adds a small daemon that reads the wanted CPU level from a file on the robot, enforces a temperature guard at 70 and 80 °C, and re-asserts the ceiling over anything else that writes it. The server drives it from the dashboard’s Power page rather than reaching in over SSH every ten seconds.
Check the CPU profile after every firmware change. It is the single easiest thing to get wrong and the most expensive.
Behaviour presets on the robot
Section titled “Behaviour presets on the robot”Behaviour presets are folders of replacement behaviour JSON. They are normally applied over SSH by the server, which keeps a copy of each original alongside so a preset can be undone; the shipped set is calm, quiet, quiet-night, sleepy, companion, playful, show-off, cat, wall-e and stock. Newer builds carry an on-robot installer so that a preset survives the slot swap a firmware update performs — otherwise an update lands you on a slot that has never had the preset applied, and the server has to notice and re-apply it.
Docked idle power saving
Section titled “Docked idle power saving”The largest change, and the one with the most caveats. See Power and battery for what it does and why it did not work first time.
The builds
Section titled “The builds”| Build | What it added |
|---|---|
3.0.1.2d | This server’s addresses and its link certificate baked in |
3.0.1.4d | Eye styles, applied from a file on the robot and re-read about once a second, so the dashboard’s eye builder changes his face live |
3.0.1.8d | Always-on detectors without behaviour control; pet, laser, illumination and salient-point events exposed to the SDK |
3.0.1.9d | The thermal daemon: CPU levels and the temperature guard, on the robot |
3.0.1.10d | Calm power mode when docked |
3.0.1.11d | The on-robot preset installer; cube app intents; cliff-stop kept armed under SDK control |
3.0.1.12d | The image built at its used size, roughly halving the slot write |
3.0.1.13d | Cliff handling in three modes with a reported stop event; a gateway reconnect when the engine restarts; the docked power save made switchable |
Builds up to 3.0.1.11d have been installed on a robot. 3.0.1.12d and
3.0.1.13d are built and staged and have never run on hardware.
The two slots
Section titled “The two slots”The robot has two system slots, A and B, plus recovery partitions that an update never writes. An update writes the slot you are not running from, marks it active, and reboots into it. The slot you were on is left exactly as it was.
That is the rollback: set the other slot active and reboot. It costs a command and a restart and gets you back to a known-good image, which is why testing a new build means installing it, not hand-copying binaries onto a running robot.
How an update reaches him
Section titled “How an update reaches him”Images live in a firmware directory on the server. Nothing is committed to git — they are around 160 MB each.
The server exposes them two ways. One is a direct download the dashboard uses. The other is the robot’s own updater endpoint: when the robot checks for an update, the server answers with a newer build if it has one, and a 404 if it does not.
Installing is a one-shot: the server stops the robot’s update timer, writes a one-shot environment file naming the image, and starts the update service. Progress comes back from the robot’s own updater state files, so the dashboard can show a phase and a percentage. When the updater reports done, the robot is restarted.
Three things about that sequence were learned the hard way, and all three are now enforced in code:
- Never restart the voice server while a robot is downloading. The download truncates and the updater aborts. The server counts downloads in flight and the supervisor and the deploy script both refuse to bounce it while any are running.
- A rebuilt server binary loses the capability to bind port 443. Without it the supervisor crash-loops the server every twelve seconds. Always deploy through the script, which re-applies it.
- Restarting the update service is not the same as starting it. The unit deletes the one-shot file when it stops, so a restart wipes the URL and the updater falls back to timer mode and does nothing.
Building
Section titled “Building”The build is Yocto, unchanged from upstream, and takes about 42 minutes clean or five minutes cached. Two constraints:
- Build as a non-root user, with a PTY. As root it fails creating a user; with
no terminal it fails on an interactive container run. Wrapping the build in
setsid script -qefc "..."satisfies both. - The signature handler is a no-op in this configuration, which means the build system never notices that a recipe’s input files changed. A recipe whose files you have edited only ships if that recipe is on the clean list. Add new recipes to it or the image quietly carries stale files.
One more trap worth knowing: the cloud client in a built image is compressed, so searching the image for its strings finds nothing. Decompress it before concluding a change did not make it in.
What is proven and what is not
Section titled “What is proven and what is not”3.0.1.11d was installed and two of its changes were confirmed on the robot: the
on-robot preset installer applied a preset, and cliff-stop stayed armed while the
server held behaviour control. Two were not: the docked power saving did not
engage, because passive status reads from the server counted as activity, and the
gateway socket reconnect did not fire on the write path. 3.0.1.13d is meant to
fix both, and has not been installed.
Everything since 3.0.1.11d is staged and has never run on hardware. The robot’s
battery failed and no firmware has been installed since. Where this documentation
describes newer behaviour, treat it as a description of the code rather than of
an observed robot.
The recovery path has not been exercised either. An update writes the inactive slot and leaves the other one bootable, and no update has yet touched the recovery partition — but flashing an unsigned image on a robot nobody makes any more is not a reversible operation if it goes wrong.