Week Three: No Hardware? No Problem
Simulation mode lets you run robots without hardware, param() references make configuration actually pleasant, math types land, and inverse kinematics learns about orientation.
What do you do when your robot parts are still in transit from China? You build a simulation mode, obviously.
Simulation Mode
The headline feature this week: robots can now run entirely in software. Pass simulation: :kinematic when starting your robot and the framework swaps in simulated actuators that honour joint velocity limits and publish motion events - but don't require any actual hardware.
# Run without hardware
MyRobot.start_link(simulation: :kinematic)
# Check mode at runtime
BB.Robot.Runtime.simulation_mode(MyRobot) # => :kinematic
The safety system still works (you must arm before commanding motion), position feedback flows through OpenLoopPositionEstimator as normal, and your LiveView dashboard lights up just like it would with real servos. The main difference? No angry servo noises at 2am.
Controllers and bridges can opt into different simulation behaviours via DSL options:
controllers do
controller :pca9685, ,
simulation: :omit # Don't start in simulation
end
This lets you test your robot's logic, supervision tree, and dashboard without touching hardware. Handy for development, CI pipelines, and waiting for slow boats from Shenzhen.
param() References: Configuration Gets Pleasant
The param() function now works everywhere in your robot DSL. Define parameters in one place, reference them anywhere - actuator options, controller configuration, even topology fields like joint limits.
parameters do
namespace :config do
namespace :robotis do
param :device, type: :string
param :baud_rate, type: :integer, default: 1_000_000
end
end
end
controllers do
controller :dynamixel,
end
Then pass values when starting:
# In your application.ex
This separates hardware configuration from robot definition. Your robot DSL describes the structure - what joints connect where, which actuators drive which joints. The runtime details (which USB port, what baud rate) come from your application config, environment variables, or wherever makes sense for your deployment.
Even better: when parameters change at runtime, actuators get notified via a handle_options/2 callback. Hot-reconfiguration without restarts.
Math Gets Serious
The core framework now includes proper mathematical types:
BB.Math.Vec3- 3D vectors backed by Nx tensors, with operations likecross/2,normalise/1, and unit vector constructorsBB.Math.Quaternion- unit quaternions for rotations, includingslerp/3,from_axis_angle/2, androtate_vector/2BB.Math.Transform- 4x4 homogeneous transformation matrices, now properly struct-wrapped
These types form the foundation for all spatial reasoning in Beam Bots. If you're passing position and orientation around, use Transform - it's the canonical representation for poses in robotics (SE(3) if you're into that sort of thing).
Orientation-Aware Inverse Kinematics
The FABRIK solver grew up. It now understands that sometimes you don't just want the gripper at a position - you want it pointing in a particular direction.
# Point the tool along the Z axis
BB.Motion.move_to(robot, :gripper, , BB.IK.FABRIK)
# Full orientation constraint
BB.Motion.move_to(robot, :gripper, , BB.IK.FABRIK)
# Or just pass a Transform
BB.Motion.move_to(robot, :gripper, target_transform, BB.IK.FABRIK)
The solver tracks orientation at each joint internally, which also fixes some edge cases with spherical joints (co-located axes like you find in shoulder and wrist assemblies).
Still early stage. Joint limits aren't enforced and collision detection doesn't exist. But it's moving in the right direction.
bb_servo_robotis: Progress Report
Good news: our upstream PR to pkinney/robotis merged on Christmas Eve. The changes add XM430 servo support, table parameterisation, and a raw read/write API.
Bad news: we're still waiting on a Hex release from upstream before we can publish bb_servo_robotis. The package works fine if you're willing to pull from git, but we want clean Hex dependencies before we call it "released".
In the meantime, the driver itself got updates:
- Wrapper GenServer pattern from bb 0.8
- Hardware error reporting to the safety system
- Configurable disarm behaviour
- Structured errors and diagnostic telemetry
When upstream publishes, we'll be ready to ship the same day.
Better Errors, Better Telemetry
The framework adopted Splode for structured error handling. Errors now have proper types, stack traces, and can be pattern-matched sensibly. No more parsing error message strings.
We also added diagnostic telemetry events. If you're running :telemetry (and you should be), you'll see performance metrics and diagnostic events flowing through. Useful for debugging and for building monitoring dashboards.
All The Releases
Since December 22:
| Package | Version | What changed |
|---|---|---|
| bb | v0.10.0 | Simulation mode, Vec3/Quaternion/Transform |
| bb | v0.9.0 | Splode errors, telemetry |
| bb | v0.8.0 | param() refs, wrapper GenServer pattern |
| bb_ik_fabrik | v0.3.0 | Orientation-aware solving |
| bb_servo_pca9685 | v0.4.0 | Structured errors |
| bb_servo_pigpio | v0.4.0 | Structured errors |
Happy New Year
To those who celebrate: enjoy the fireworks, make some resolutions you won't keep, and try not to think about how much work is waiting for you in January.
To those who don't: enjoy the quiet internet. Again.
See you in 2025. Wait, we're already in 2025. See you next year. Which is also 2025. You know what I mean.
Links
- bb on Hex (v0.10.0)
- bb_ik_fabrik on Hex (v0.3.0)
- bb_liveview on Hex (v0.2.0)
- bb_kino on Hex (v0.2.0)
- bb_servo_pca9685 on Hex (v0.4.0)
- bb_servo_pigpio on Hex (v0.4.0)
- bb_servo_robotis on GitHub (coming to Hex soon)
- Discord