# `BB.Robot.Joint`
[🔗](https://github.com/beam-bots/bb/blob/main/lib/bb/robot/joint.ex#L5)

An optimised joint representation with all units converted to SI floats.

Joints connect a parent link to a child link and define the kinematic
relationship between them.

# `axis`

```elixir
@type axis() :: {float(), float(), float()}
```

Joint axis of rotation/translation as a normalised unit vector {x, y, z}.

# `dynamics`

```elixir
@type dynamics() :: %{damping: float() | nil, friction: float() | nil}
```

Joint dynamics parameters.

- `damping`: viscous damping coefficient
  - For revolute: N·m·s/rad
  - For prismatic: N·s/m
- `friction`: Coulomb friction
  - For revolute: N·m
  - For prismatic: N

# `joint_type`

```elixir
@type joint_type() ::
  :revolute | :continuous | :prismatic | :fixed | :floating | :planar
```

# `limits`

```elixir
@type limits() :: %{
  lower: float() | nil,
  upper: float() | nil,
  velocity: float(),
  effort: float(),
  acceleration: float() | nil
}
```

Joint limits.

For revolute/continuous joints:
- `lower`/`upper`: angle limits in radians
- `velocity`: max angular velocity in rad/s
- `effort`: max torque in N·m
- `acceleration`: max angular acceleration in rad/s² (optional)

For prismatic joints:
- `lower`/`upper`: position limits in meters
- `velocity`: max linear velocity in m/s
- `effort`: max effort in N·m (as defined in DSL)
- `acceleration`: max linear acceleration in m/s² (optional)

# `origin`

```elixir
@type origin() :: %{
  position: {float(), float(), float()},
  orientation: {float(), float(), float()}
}
```

Joint origin transform from parent to child frame.

- `position`: {x, y, z} translation in meters
- `orientation`: {roll, pitch, yaw} rotation in radians (XYZ Euler angles)

# `t`

```elixir
@type t() :: %BB.Robot.Joint{
  actuators: [atom()],
  axis: axis() | nil,
  child_link: atom(),
  dynamics: dynamics() | nil,
  limits: limits() | nil,
  name: atom(),
  origin: origin() | nil,
  parent_link: atom(),
  sensors: [atom()],
  type: joint_type()
}
```

# `linear?`

```elixir
@spec linear?(t()) :: boolean()
```

Check if this joint is linear (prismatic).

# `movable?`

```elixir
@spec movable?(t()) :: boolean()
```

Check if this joint has any degrees of freedom.

# `rotational?`

```elixir
@spec rotational?(t()) :: boolean()
```

Check if this joint is rotational (revolute or continuous).

---

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