Search documentation of bb

# BB.Motion.Tracker behaviour (bb v0.8.0)

View Source

Behaviour for continuous position tracking with IK.

Trackers maintain an ongoing IK solution loop, continuously solving for updated targets and sending actuator commands. This is useful for:

- Following a moving target (visual tracking)
- Smooth trajectory interpolation
- Real-time position control from external sources

## Implementing a Tracker

Trackers are typically GenServers that:

1. Run a periodic solve loop at a configurable rate
2. Accept target updates via `update_target/2`
3. Send actuator commands on each successful solve
4. Report status including tracking error and solve statistics

## Callbacks

- `start_tracking/5` - Begin tracking a target link
- `update_target/2` - Update the current target position
- `status/1` - Get current tracking status
- `stop_tracking/2` - Stop tracking and optionally return final positions

## Example Implementation

See `BB.IK.FABRIK.Tracker` for a reference implementation.

## Usage Pattern

    # Start tracking
    {:ok, tracker} = BB.IK.FABRIK.Tracker.start_link(
      robot: MyRobot,
      target_link: :gripper,
      initial_target: {0.3, 0.2, 0.1},
      update_rate: 30
    )

    # Update target from vision callback
    BB.IK.FABRIK.Tracker.update_target(tracker, new_target)

    # Check status
    %{residual: 0.001, tracking: true} = BB.IK.FABRIK.Tracker.status(tracker)

    # Stop and get final positions
    {:ok, positions} = BB.IK.FABRIK.Tracker.stop(tracker)

# Summary

## Types

positions()
status()
target()
tracker_state()

## Callbacks

start_tracking(robot, robot_state, target_link, initial_target, opts)

Start tracking a target link.

status(state)

Get current tracking status.

stop_tracking(state, opts)

Stop tracking.

update_target(state, target)

Update the current target position.

# Types

# positions()

    @type positions() :: BB.IK.Solver.positions()

# status()

    @type status() :: %{
      tracking: boolean(),
      target: target() | nil,
      residual: float() | nil,
      iterations: non_neg_integer(),
      update_rate: pos_integer(),
      last_update: DateTime.t() | nil
    }

# target()

    @type target() :: BB.IK.Solver.target()

# tracker_state()

    @type tracker_state() :: term()

# Callbacks

# start_tracking(robot, robot_state, target_link, initial_target, opts)

    @callback start_tracking(
      robot :: module() | BB.Robot.t(),
      robot_state :: BB.Robot.State.t(),
      target_link :: atom(),
      initial_target :: target(),
      opts :: keyword()
    ) :: {:ok, tracker_state()} | {:error, term()}

Start tracking a target link.

## Options

Required:

- `:robot` - Robot module or struct
- `:target_link` - Name of the link to track
- `:initial_target` - Starting target position

Optional:

- `:update_rate` - Solve frequency in Hz (default: 20)
- `:delivery` - Actuator command delivery mode (default: `:direct`)
- `:max_iterations` - Maximum solver iterations per update
- `:tolerance` - Convergence tolerance

## Returns

- `{:ok, state}` - Tracking started
- `{:error, reason}` - Failed to start

# status(state)

    @callback status(state :: tracker_state()) :: status()

Get current tracking status.

## Returns

Status map containing:

- `tracking` - Whether actively tracking
- `target` - Current target position
- `residual` - Distance from end-effector to target
- `iterations` - Solver iterations on last update
- `update_rate` - Current update frequency
- `last_update` - Timestamp of last successful solve

# stop_tracking(state, opts)

    @callback stop_tracking(state :: tracker_state(), opts :: keyword()) ::
      {:ok, positions()} | {:error, term()}

Stop tracking.

## Options

- `:hold` - Whether to send hold commands to actuators (default: false)

## Returns

- `{:ok, positions}` - Final joint positions
- `{:error, reason}` - Stop failed

# update_target(state, target)

    @callback update_target(state :: tracker_state(), target :: target()) ::
      {:ok, tracker_state()} | {:error, term()}

Update the current target position.

The tracker will solve for the new target on its next update cycle.

## Returns

- `{:ok, state}` - Target updated
- `{:error, reason}` - Update failed (e.g., tracker stopped)