# `BB.Sensor.OpenLoopPositionEstimator`
[🔗](https://github.com/beam-bots/bb/blob/main/lib/bb/sensor/open_loop_position_estimator.ex#L5)

A "sensor" that estimates joint position for open-loop control systems.

This sensor subscribes to `BB.Message.Actuator.BeginMotion` messages from a
paired actuator and uses easing functions to estimate the current joint
position during motion. It publishes `BB.Message.Sensor.JointState` messages
at a configurable rate.

Use this sensor with actuators that don't provide position feedback (e.g.,
RC servos, open-loop stepper motors). The estimator works with any joint
type (revolute, prismatic, etc.) as it operates on raw position values.

## Options

- `actuator` - Name of the actuator to subscribe to (required)
- `easing` - Easing function for position interpolation (default: `:linear`)
- `publish_rate` - Rate to publish position updates during motion (default: 50 Hz)
- `max_silence` - Maximum time between publishes when idle (default: 5 seconds)

## Easing Functions

The following easing functions are available (see [easings.net](https://easings.net)
for visualisations):

- `:linear` - Constant velocity (default)
- `:ease_in_sine`, `:ease_out_sine`, `:ease_in_out_sine` - Sinusoidal
- `:ease_in_quad`, `:ease_out_quad`, `:ease_in_out_quad` - Quadratic
- `:ease_in_cubic`, `:ease_out_cubic`, `:ease_in_out_cubic` - Cubic
- `:ease_in_quartic`, `:ease_out_quartic`, `:ease_in_out_quartic` - Quartic
- `:ease_in_quintic`, `:ease_out_quintic`, `:ease_in_out_quintic` - Quintic
- `:ease_in_expo`, `:ease_out_expo`, `:ease_in_out_expo` - Exponential
- `:ease_in_circular`, `:ease_out_circular`, `:ease_in_out_circular` - Circular

## Example DSL Usage

    joint :shoulder, type: :revolute do
      limit lower: ~u(-45 degree), upper: ~u(45 degree), velocity: ~u(60 degree_per_second)

      actuator :servo, {BB.Servo.Pigpio.Actuator, pin: 17}
      sensor :feedback, {BB.Sensor.OpenLoopPositionEstimator,
        actuator: :servo,
        easing: :ease_in_out_quad
      }
    end

## How It Works

1. Subscribes to `BeginMotion` messages from the named actuator
2. When motion begins, captures initial position, target, and expected arrival time
3. Ticks at publish_rate during animation, interpolating position with easing
4. Uses GenServer timeout for heartbeat publishes when idle
5. Ensures final position is published even under system load

---

*Consult [api-reference.md](api-reference.md) for complete listing*
