Summary
Actuators receive commands by subscribing to [:actuator | path], and any process can publish there. BB.Actuator.set_position/4 and friends all publish to [:actuator | path] (lib/bb/actuator.ex:366-368). There is no notion of who owns a joint, no command mux, and no priority.
The collision is already visible in the ecosystem: bb_pid_controller's default output_topic is [:actuator, :base_link, :shoulder, :servo] (bb_pid_controller/lib/bb/pid/controller.ex:50) — a PID loop publishes its output directly onto a servo's actuator command topic, the exact same channel a command handler or BB.Actuator.set_position/4 call uses.
Why it matters
Today there's usually a single commander per joint, so it works. The moment a PID loop, a command/sequence handler, and (per the roadmap) a policy runner coexist over the same joint, it's last-writer-wins at PubSub delivery order — with:
- no way to ask "who is currently commanding this joint?"
- no priority (e.g. a safety/teleop override should pre-empt an autonomous command)
- no mux or hand-off protocol between commanders
This will bite the first time someone layers bb_pid_controller over an executing command, and again when bb_policy's runner shares a joint with anything else.
Worth deciding
What the arbitration model should be — e.g. a per-joint owner/lease, a priority field on actuator commands, or an explicit mux process per actuator. Relevant because the topic taxonomy is becoming the de-facto ABI (see the topic-paths-as-ABI finding), so an arbitration concept is cheaper to introduce before more commanders exist than after.
Summary
Actuators receive commands by subscribing to
[:actuator | path], and any process can publish there.BB.Actuator.set_position/4and friends all publish to[:actuator | path](lib/bb/actuator.ex:366-368). There is no notion of who owns a joint, no command mux, and no priority.The collision is already visible in the ecosystem:
bb_pid_controller's defaultoutput_topicis[:actuator, :base_link, :shoulder, :servo](bb_pid_controller/lib/bb/pid/controller.ex:50) — a PID loop publishes its output directly onto a servo's actuator command topic, the exact same channel a command handler orBB.Actuator.set_position/4call uses.Why it matters
Today there's usually a single commander per joint, so it works. The moment a PID loop, a command/sequence handler, and (per the roadmap) a policy runner coexist over the same joint, it's last-writer-wins at PubSub delivery order — with:
This will bite the first time someone layers
bb_pid_controllerover an executing command, and again whenbb_policy's runner shares a joint with anything else.Worth deciding
What the arbitration model should be — e.g. a per-joint owner/lease, a priority field on actuator commands, or an explicit mux process per actuator. Relevant because the topic taxonomy is becoming the de-facto ABI (see the topic-paths-as-ABI finding), so an arbitration concept is cheaper to introduce before more commanders exist than after.