Skip to content

apps-sandbox/dotbot-next: add a control-loop-free app on the new fix sequence - #422

Closed
geonnave wants to merge 4 commits into
DotBots:mainfrom
geonnave:control-fw
Closed

geonnave wants to merge 4 commits into
DotBots:mainfrom
geonnave:control-fw

Conversation

@geonnave

Copy link
Copy Markdown
Contributor

Adds apps-sandbox/dotbot-next, a sandboxed DotBot application with no control loop, and takes the import library carrying swarmit's new fix-sequence entry point.

Requires DotBots/swarmit#161, which adds swarmit_localization_get_fix() and removes the secure side's displacement gate on position solves. The cmse_implib.a here is regenerated from that branch; the veneer table grows by one entry and every existing veneer address moves, which is why all sandbox applications are rebuilt even though six of them are unchanged in source.

The new application stays joined, polls the position the secure side solves, samples the wheel encoders, advertises in the same byte layout as apps-sandbox/dotbot, and accepts direct motor commands. That is all it does: no state estimator, no steering law, no waypoint sequencing, no displacement gate on incoming fixes. It exists to measure the plant and the position source before any control layer sits on top of them, and to be the base those layers get added to one at a time, each testable against only the layers below it. apps-sandbox/dotbot is untouched and keeps using the original entry point.

Three structural choices a reviewer should look at, all documented in the application's README.

One periodic tick drives everything, with slower activities dividing it down. The alternative, a channel per period, consumes all three usable RTC0 channels and leaves nothing for the encoder sampling rate a velocity loop needs.

swarmit_keep_alive() is what runs the lighthouse solve and republishes it, so the rate it is called at is the position rate, and reading the position without having just called it returns the previous solve. The two are deliberately adjacent and must stay that way.

The command timeout is unconditional. apps-sandbox/dotbot skips it in automatic mode, which leaves an autonomously driving robot with no deadman at all; this application has no autonomous mode, so silence always means stop. Its timeout arithmetic also uses a masked difference, because db_timer_ticks() returns a 24-bit counter that wraps every 512 s and a plain now > then + delay comparison is false for the entire pass after a wrap.

The README records what was carried over from the existing applications deliberately and what was changed, so the reasoning does not have to be rediscovered.

Validation: builds only. 8 applications across sandbox-dotbot-v2, sandbox-dotbot-v3 and sandbox-nrf5340dk in both Debug and Release, 48 builds, zero warnings, make check-format clean. nm on the linked image confirms the new symbol resolving against the regenerated import library. Nothing has run on hardware.

One consequence to confirm on a bench: clearing the solve-available flag on consumption means that if sweeps arrive more slowly than the keepalive, position updates stop between sweeps instead of republishing the last solve. Shared data retains its last value so the status frame is unaffected, but the observed fix rate may read lower than the previous behaviour implied. That is the honest figure rather than a regression, and it should be confirmed as what is actually seen.

@geonnave

Copy link
Copy Markdown
Contributor Author

Correction to the PR description, affecting flash order.

The description says every existing veneer address moves. It does not: 8 of the 12 entries keep their addresses and only the four after the insertion point shift. Detail and the nm output are in DotBots/swarmit#161.

The consequence is that a bootloader/application mismatch does not fail cleanly in either direction. Keepalive and the advertisement keep working because those veneers did not move, while the SPIM4 handler lands on the wrong entry, storms an uncleared interrupt, starves thread mode and lets the one second watchdog reset-loop the robot. Since applications flash over the air and bootloaders need a cable, the natural rollout order is the broken one.

Concretely, for anyone testing this branch: cable-flash the bootloader from swarmit#161 on a robot before flashing any application from this branch onto it, and do not send these applications over the air to robots still running the current bootloader.

@geonnave

Copy link
Copy Markdown
Contributor Author

Resolved: the compatibility half of the note above is not a concern for this project. Old firmware images are not supported, and the fleet is reflashed and re-released as a unit, so the veneer table reordering needs no mitigation and no version handshake.

What survives is a rollout instruction rather than a compatibility one: applications flash over the air and bootloaders need a cable, so cable the bootloader onto a robot before putting a new application on it. Updating applications first passes every robot through the broken state.

The two real defects found in the same review are fixed on this branch: a solve that never ran is no longer published as a fresh fix (which also removes a (0,0) publish on the first call), and the status frame now reads the position under the mutex that writes it.

@geonnave
geonnave changed the base branch from develop to main September 8, 2026 11:59
The secure side gained swarmit_localization_get_fix(), which reports a
position together with the sequence of the solve it came from. Adding
an entry moves every veneer address, so all the applications here are
rebuilt against this blob whether or not they call the new function,
and a bot only runs them once its bootloader has been reflashed over
cable from the matching swarmit build.

AI-assisted: Claude Opus 5
The advertisement used to zero the accumulator, so counts belonged to
whoever read first and an estimator added later would see nothing. The
tick now drains the destructive hardware read into totals that are never
cleared, and each consumer takes a delta against its own cursor. Totals
are unsigned so the wrap at 2^32 subtracts correctly rather than being
undefined.

AI-assisted: Claude Opus 5
@geonnave

Copy link
Copy Markdown
Contributor Author

Superseded by #424, which carries these commits first together with the import library regenerated for the float32 calibration work (DotBots/swarmit#165). The description and review here stay the reference for dotbot-next. Closing in favour of #424.

@geonnave geonnave closed this Sep 21, 2026
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