BB.TUI.Panels.Joints (BB.TUI v0.5.0)

Copy Markdown View Source

Joint control panel — displays joint positions with type, units, and visual position bars.

Shows each joint's name, type (rev/pri/con), current position in human-readable units (degrees or mm), and a bar indicating position within the joint's limits. Simulated joints are marked with a SIM tag.

Pure function — takes state, returns a widget struct.

Summary

Functions

Formats a joint limit value in human-readable units (degrees or mm).

Formats a joint name, appending SIM tag for simulated joints.

Formats position with appropriate units based on joint type.

Formats the joint type as a short label.

Renders the joints panel as a Table widget with columns for name, type, position with units, and a visual position bar.

Functions

format_limit(val, arg2)

@spec format_limit(number(), map()) :: String.t()

Formats a joint limit value in human-readable units (degrees or mm).

Examples

iex> BB.TUI.Panels.Joints.format_limit(1.5708, %{type: :revolute})
"90"

iex> BB.TUI.Panels.Joints.format_limit(-1.5708, %{type: :revolute})
"-90"

iex> BB.TUI.Panels.Joints.format_limit(0.037, %{type: :prismatic})
"37"

format_name(name, arg2)

@spec format_name(atom(), map()) :: String.t()

Formats a joint name, appending SIM tag for simulated joints.

A joint is simulated when it has an empty actuators list.

Examples

iex> BB.TUI.Panels.Joints.format_name(:elbow, %{actuators: []})
"elbow SIM"

iex> BB.TUI.Panels.Joints.format_name(:elbow, %{actuators: [:motor]})
"elbow"

iex> BB.TUI.Panels.Joints.format_name(:elbow, %{})
"elbow"

format_position(transform, arg2)

@spec format_position(number() | nil | struct(), map()) :: String.t()

Formats position with appropriate units based on joint type.

Revolute/continuous joints show degrees, prismatic joints show millimeters. Multi-DoF configurations render as a compact pose — (x, y, θ°) in meters for planar, the translation (x, y, z) in meters for floating; both are display-only.

Examples

iex> BB.TUI.Panels.Joints.format_position(1.5708, %{type: :revolute})
"90.0°"

iex> BB.TUI.Panels.Joints.format_position(0.030, %{type: :prismatic})
"30.0 mm"

iex> BB.TUI.Panels.Joints.format_position(nil, %{type: :revolute})
"N/A"

iex> BB.TUI.Panels.Joints.format_position(BB.Math.Transform2D.new(0.12, -0.3, 1.5708), %{type: :planar})
"(0.12, -0.30, 90.0°)"

iex> BB.TUI.Panels.Joints.format_position(BB.Math.Transform.identity(), %{type: :floating})
"(0.00, 0.00, 0.00)"

format_type(arg1)

@spec format_type(map()) :: String.t()

Formats the joint type as a short label.

Examples

iex> BB.TUI.Panels.Joints.format_type(%{type: :revolute})
"rev"

iex> BB.TUI.Panels.Joints.format_type(%{type: :prismatic})
"pri"

iex> BB.TUI.Panels.Joints.format_type(%{type: :continuous})
"con"

iex> BB.TUI.Panels.Joints.format_type(%{type: :planar})
"pla"

iex> BB.TUI.Panels.Joints.format_type(%{type: :floating})
"flo"

iex> BB.TUI.Panels.Joints.format_type(%{type: :fixed})
"fix"

iex> BB.TUI.Panels.Joints.format_type(%{})
"-"

render(state, focused?)

@spec render(BB.TUI.State.t(), boolean()) :: struct()

Renders the joints panel as a Table widget with columns for name, type, position with units, and a visual position bar.

Examples

iex> entries = %{shoulder: %{joint: %{name: :shoulder, type: :revolute, limits: %{lower: -1.57, upper: 1.57}}, position: 0.0}}
iex> state = %BB.TUI.State{joints: %BB.TUI.State.Joints{entries: entries}}
iex> %ExRatatui.Widgets.Table{header: header} = BB.TUI.Panels.Joints.render(state, false)
iex> header
["Joint", "Type", "Position", "Target"]