Beam Bots Logo

BB.IK.FABRIK

CILicense: Apache 2.0Hex version badgeHexdocs badgeREUSE statusAsk DeepWiki

A FABRIK-based inverse kinematics solver for the Beam Bots robotics framework.

FABRIK (Forward And Backward Reaching Inverse Kinematics) is an iterative algorithm that computes joint angles needed to position an end-effector at a target location. It works by alternately reaching from the end-effector toward the target, then from the base back to maintain segment lengths.

Features

Installation

Add bb_ik_fabrik to your list of dependencies in mix.exs:

def deps do
[
{:bb_ik_fabrik, "~> 0.7.0"}
]
end

Usage

# Define your robot using the BB DSL
robot = MyRobot.robot()
# Create initial state
{:ok, state} = BB.Robot.State.new(robot)
# Define a target position for the end-effector
target = {0.3, 0.2, 0.1}
# Solve inverse kinematics
case BB.IK.FABRIK.solve(robot, state, :end_effector, target) do
{:ok, positions, meta} ->
# Apply the solved positions to the robot state
BB.Robot.State.set_positions(state, positions)
IO.puts("Solved in #{meta.iterations} iterations")
IO.puts("Final distance to target: #{meta.residual}m")
{:error, %BB.Error.Kinematics.Unreachable{residual: residual, positions: positions}} ->
# Target is beyond the robot's reach
IO.puts("Target unreachable, best distance: #{residual}m")
# positions contains best-effort joint values
{:error, %BB.Error.Kinematics.NoSolution{}} ->
IO.puts("Failed to converge within max iterations")
end

Solving with Options

BB.IK.FABRIK.solve(robot, state, :end_effector, target,
max_iterations: 100, # Maximum FABRIK iterations (default: 50)
tolerance: 0.001, # Position tolerance in metres (default: 1.0e-4)
orientation_tolerance: 0.1, # Orientation tolerance in radians (default: 0.01)
respect_limits: true # Clamp to joint limits (default: true)
)

Using solve_and_update/5

For convenience, solve_and_update/5 solves IK and updates the state in one call:

case BB.IK.FABRIK.solve_and_update(robot, state, :end_effector, target) do
{:ok, positions, meta} ->
# State has already been updated
:ok
{:error, %BB.Error.Kinematics.Unreachable{} = error} ->
# State is unchanged on error
{:error, error}
end

Target Formats

Targets can be specified as:

# Position only (Vec3)
target = BB.Math.Vec3.new(0.3, 0.2, 0.1)
# Position with axis constraint ("point tool in this direction")
target = {BB.Math.Vec3.new(0.3, 0.2, 0.1), {:axis, BB.Math.Vec3.new(0.0, 0.0, -1.0)}}
# Position with full orientation (quaternion)
quat = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 4)
target = {BB.Math.Vec3.new(0.3, 0.2, 0.1), {:quaternion, quat}}
# 4x4 homogeneous transform (extracts both position and orientation)
target = BB.Math.Transform.from_position_quaternion(
BB.Math.Vec3.new(0.3, 0.2, 0.1),
BB.Math.Quaternion.identity()
)

When using orientation constraints, the result metadata includes orientation_residual (in radians) alongside the position residual.

Supported Arm Configurations

FABRIK works best with simple planar or spatial arms where:

Works Well

How a target is solved

Classic FABRIK moves points as though every joint were a ball joint, so the configuration it settles on generally has no counterpart in any pose the robot can hold. For a position target this implementation keeps FABRIK's backward reach but treats its answer as desired directions: the forward pass walks base to tip choosing, for each joint, the rotation about its real world axis that carries its links closest to those directions, clamped to its limits, and regenerates the positions beyond it by forward kinematics.

Every pose considered is therefore one the robot can actually hold, and the joint values are the solver's output rather than something recovered from a point cloud afterwards.

Orientation rides the same fit: three points sit rigidly on the target link's axes, and putting them where they are wanted is the same as pointing the frame where it is wanted.

Limitations

When to Use a Different Solver

Consider analytical IK or Jacobian-based methods when:

Documentation

Full documentation is available at HexDocs.