<!--
SPDX-FileCopyrightText: 2026 James Harton
SPDX-License-Identifier: Apache-2.0
-->
<img src="https://github.com/beam-bots/bb/blob/main/logos/beam_bots_logo.png?raw=true" alt="Beam Bots Logo" width="250" />
# BB.Reactor
[](https://github.com/beam-bots/bb_reactor/actions/workflows/ci.yml)
[](https://opensource.org/licenses/Apache-2.0)
[](https://hex.pm/packages/bb_reactor)
[](https://api.reuse.software/info/github.com/beam-bots/bb_reactor)
Spark DSL extension for integrating [Reactor](https://hexdocs.pm/reactor) with the [BB robotics framework](https://github.com/beam-bots/bb).
## Installation
Add `bb_reactor` to your dependencies in `mix.exs`:
```elixir
def deps do
[
{:bb_reactor, "~> 0.1"}
]
end
```
## Usage
```elixir
defmodule MyRobot.PickAndPlace do
use Reactor, extensions: [BB.Reactor]
input :pick_pose
input :place_pose
# Wait for robot to be ready
wait_for_state :ready do
states [:idle]
timeout 5000
end
# Execute movement command
command :approach do
command :move_to_pose
argument :target, input(:pick_pose)
wait_for :ready
end
# Close gripper
command :grip do
command :close_gripper
wait_for :approach
end
# Wait for force sensor event
wait_for_event :gripped do
path [:sensor, :force]
timeout 2000
wait_for :grip
end
# Move to place position with compensation
command :retreat do
command :move_to_pose
argument :target, input(:place_pose)
wait_for :gripped
compensate :return_home
end
return :retreat
end
# Run the reactor
Reactor.run(MyRobot.PickAndPlace, inputs, %{private: %{bb_robot: MyRobot}})
```
## Entities
### `command`
Execute a BB command with safety handling and compensation support.
```elixir
command :move do
command :move_to_pose # The BB command to execute
argument :target, input(:pose) # Arguments passed to the command
timeout 30_000 # Optional timeout (default: :infinity)
compensate :return_home # Optional compensation command for undo
end
```
### `wait_for_event`
Wait for a PubSub event matching a pattern.
```elixir
wait_for_event :force_detected do
path [:sensor, :force_torque] # PubSub path to subscribe to
timeout 5000 # Optional timeout
message_types [ForceTorque] # Optional: filter by message type
filter &MyFilters.threshold?/1 # Optional: custom filter function
end
```
### `wait_for_state`
Wait for the robot to reach a specific state.
```elixir
wait_for_state :wait_for_idle do
states [:idle] # Target states (any-of matching)
timeout 5000 # Optional timeout
end
```
## Safety Integration
The `BB.Reactor.Middleware.Safety` middleware can be added to report reactor errors to the BB safety system:
```elixir
defmodule MyRobot.SafeReactor do
use Reactor, extensions: [BB.Reactor]
middlewares do
middleware BB.Reactor.Middleware.Safety
end
# ... steps
end
```
This allows the robot's `auto_disarm_on_error` configuration to control whether errors trigger automatic disarm.
## Documentation
- [HexDocs](https://hexdocs.pm/bb_reactor)
- [BB Framework](https://hexdocs.pm/bb)
- [Reactor](https://hexdocs.pm/reactor)
## License
Apache License 2.0