# Understanding Newton Joint Types: D6, Ball, Prismatic, Revolute, Fixed, and Cable

> Explore Newton joint types like D6, Ball, Prismatic, Revolute, Fixed, and Cable. Master mechanical connections in the Newton physics engine and optimize your simulations.

- Repository: [Newton Physics/newton](https://github.com/newton-physics/newton)
- Tags: documentation
- Published: 2026-03-19

---

**Newton physics engine represents mechanical connections through a dual-layer system where `JointType` provides the public API catalog (D6, Ball, Prismatic, Revolute, Fixed, Cable) while `JointDoFType` handles internal solver representation with specific degrees-of-freedom constraints.**

The `newton-physics/newton` repository implements a sophisticated rigid-body simulation framework that categorizes mechanical connections through distinct Newton joint types. Understanding the relationship between the user-facing enumeration and the internal solver representation is essential for correctly configuring robotic mechanisms, character joints, and physics-based animations.

## The Two-Layer Architecture: JointType vs. JointDoFType

Newton’s joint system separates public interface from internal implementation through two complementary enumerations defined in separate modules.

### JointType: The Public API Surface

The `JointType` enumeration in [`newton/_src/sim/enums.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/enums.py) (lines 46-69) serves as the primary contract for users, importers, and external tools such as USD Physics and MuJoCo. It defines the categorical joint types that appear in scene descriptions and configuration files.

```python

# From newton/_src/sim/enums.py

class JointType(enum.IntEnum):
    PRISMATIC = 0   # 1 translational DoF

    REVOLUTE  = 1   # 1 rotational DoF

    BALL      = 2   # 3 rotational DoF (quaternion)

    FIXED     = 3   # 0 DoF – fully locked

    FREE      = 4   # 6 DoF (7 coordinates – 3 pos + 4 quat)

    DISTANCE  = 5   # 6 DoF, distance constraint

    D6        = 6   # Generic 6-DoF joint (any combination)

    CABLE     = 7   # 1 linear stretch + 1 isotropic bend/twist DoF

```

### JointDoFType: The Internal Solver Representation

The `JointDoFType` enumeration in [`newton/_src/solvers/kamino/_src/core/joints.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/solvers/kamino/_src/core/joints.py) (lines 87-124) encodes the internal representation that couples **degrees-of-freedom (DoF)**, **coordinate count**, and **constraint sets**. This abstraction allows the Kamino solver to allocate state vectors and constraint rows efficiently.

Each variant stores:
- `num_coords`: Scalar values needed for configuration (e.g., quaternion = 4)
- `num_dofs`: Independent velocity components
- `num_cts`: Bilateral kinematic constraints imposed

## Complete Guide to Newton Joint Types

The following sections detail each joint type’s behavior, coordinate requirements, and constraint structure as implemented in the Newton physics engine.

### D6 (Generic 6-DoF)

The **D6** joint provides generic 6-DoF configurability, supporting any combination of translational and rotational axes. Internally, the solver maps specific D6 configurations to specialized `JointDoFType` variants including `CARTESIAN`, `CYLINDRICAL`, `UNIVERSAL`, and `GIMBAL` based on the enabled axes.

- **Coordinates**: Up to 7 (depends on enabled axes)
- **DoFs**: Up to 6 (3 translational + 3 rotational)
- **Constraints**: `6 - num_enabled_axes` (or 0 for free)

### Ball (Spherical)

The **Ball** joint permits three rotational degrees of freedom while locking all translation. It uses a quaternion representation internally to avoid gimbal lock, mapping to the `SPHERICAL` `JointDoFType`.

- **Coordinates**: 4 (quaternion)
- **DoFs**: 3 (rotational)
- **Constraints**: 3 (translational constraints)

### Prismatic

The **Prismatic** joint allows motion along a single translational axis, functioning like a piston or linear guide. It constrains all rotation and two translation axes, corresponding to the `PRISMATIC` `JointDoFType`.

- **Coordinates**: 1 (linear distance)
- **DoFs**: 1 (translational)
- **Constraints**: 5 (`T_y`, `T_z`, `R_x`, `R_y`, `R_z`)

### Revolute

The **Revolute** joint permits rotation around a single axis, acting as a hinge. It constrains all three translations and two rotations, mapping to the `REVOLUTE` `JointDoFType`.

- **Coordinates**: 1 (angle)
- **DoFs**: 1 (rotational)
- **Constraints**: 5 (`T_x`, `T_y`, `T_z`, `R_y`, `R_z`)

### Fixed

The **Fixed** joint rigidly attaches two bodies, allowing zero relative motion. It applies six bilateral constraints to lock all degrees of freedom, corresponding to the `FIXED` `JointDoFType`.

- **Coordinates**: 0
- **DoFs**: 0
- **Constraints**: 6 (fully locked)

### Cable

The **Cable** joint is currently a specialized `JointType` entry representing flexible connections with **1 linear stretch degree of freedom** and **1 isotropic bend/twist degree of freedom**. Unlike other joints, it does not yet have a dedicated `JointDoFType` variant; the engine treats it as a special case in the solver.

- **Coordinates**: 2
- **DoFs**: 2 (1 translational + 1 rotational)
- **Constraints**: 4

## Mapping Between Representations

The conversion between public `JointType` and internal `JointDoFType` occurs through explicit mapping tables in [`newton/_src/solvers/kamino/_src/core/joints.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/solvers/kamino/_src/core/joints.py) (lines 66-80).

The static method `JointDoFType.to_newton()` implements this mapping:

```python

# Mapping table from JointDoFType.to_newton (lines 66-80)

_MAP_TO_NEWTON = {
    JointDoFType.FREE:        JointType.FREE,
    JointDoFType.REVOLUTE:    JointType.REVOLUTE,
    JointDoFType.PRISMATIC:   JointType.PRISMATIC,
    JointDoFType.SPHERICAL:   JointType.BALL,
    JointDoFType.FIXED:       JointType.FIXED,
    # D6-family joints map to the generic D6 type

    JointDoFType.CARTESIAN:   JointType.D6,
    JointDoFType.CYLINDRICAL: JointType.D6,
    JointDoFType.UNIVERSAL:   JointType.D6,
    JointDoFType.GIMBAL:      JointType.D6,
}

```

This explicit dictionary approach makes the system extensible—adding a new joint type requires only adding entries to the enum and updating the mapping table.

## Practical Implementation Examples

### Creating a Revolute Joint Descriptor

To instantiate a revolute joint in Newton, use the `JointDescriptor` class from `newton.geometry` with `JointDoFType.REVOLUTE`:

```python
from newton.geometry import JointDescriptor, JointActuationType, JointDoFType

# A simple revolute joint that is position-controlled

rev_joint = JointDescriptor(
    name="elbow",
    act_type=JointActuationType.POSITION,
    dof_type=JointDoFType.REVOLUTE,
    bid_B=0,               # base body index

    bid_F=1,               # follower body index

    B_r_Bj=[0.0, 0.0, 0.0],  # joint origin in base frame

    F_r_Fj=[0.0, 0.0, 0.0],  # joint origin in follower frame

    k_p_j=1.0,             # PD proportional gain

    k_d_j=0.1,             # PD derivative gain

)

print(rev_joint)          # human-readable summary

print("Newton JointType →", rev_joint.dof_type.to_newton())

```

*Source:* `JointDescriptor` definition in [`newton/_src/solvers/kamino/_src/core/joints.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/solvers/kamino/_src/core/joints.py) (lines 81-95).

### Converting JointType to JointDoFType

When importing scenes from external formats like USD, you may need to convert the generic `JointType` back to a specific `JointDoFType`:

```python
from newton._src.sim.enums import JointType
from newton._src.solvers.kamino._src.core.joints import JointDoFType
import numpy as np

# Suppose we read a joint from a USD file – it says type is D6

joint_type = JointType.D6

# Infer the most specific DoF type (requires extra info such as axis count)

# Here we assume a cylindrical joint (1 translational + 1 rotational)

dof_type = JointDoFType.from_newton(
    type=joint_type,
    q_count=2, qd_count=2,
    dof_dim=(1, 1),               # 1 translational, 1 rotational axis

    limit_lower=np.array([-1e3, -np.pi]),
    limit_upper=np.array([1e3, np.pi]),
)

print(dof_type)  # JointDoFType.CYLINDRICAL

```

*Source:* `JointDoFType.from_newton` logic in [`newton/_src/solvers/kamino/_src/core/joints.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/solvers/kamino/_src/core/joints.py) (lines 86-112).

### Running the Basic Joints Demo

Newton includes a ready-to-run demonstration that visualizes all supported joint types:

```bash
uv run -m newton.examples basic_joints

```

This command executes the example script at [`newton/examples/basic/example_basic_joints.py`](https://github.com/newton-physics/newton/blob/main/newton/examples/basic/example_basic_joints.py), which constructs a miniature world, adds bodies with each joint type (D6, Ball, Prismatic, Revolute, Fixed, and Cable), and renders a snapshot to `docs/images/examples/example_basic_joints.jpg`.

## Summary

- Newton joint types are defined by two complementary enumerations: the public `JointType` in [`newton/_src/sim/enums.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/enums.py) and the internal `JointDoFType` in [`newton/_src/solvers/kamino/_src/core/joints.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/solvers/kamino/_src/core/joints.py).
- **D6** joints provide generic 6-DoF configurability, mapping internally to specialized `JointDoFType` variants (`CARTESIAN`, `CYLINDRICAL`, `UNIVERSAL`, `GIMBAL`) based on enabled axes.
- **Ball**, **Prismatic**, **Revolute**, and **Fixed** joints correspond directly to `SPHERICAL`, `PRISMATIC`, `REVOLUTE`, and `FIXED` internal types with specific coordinate counts and constraint structures.
- **Cable** joints are currently represented as a specialized `JointType` with 2 DoFs (stretch and twist) without a dedicated `JointDoFType` variant.
- Conversion between representations uses explicit mapping tables in `JointDoFType.to_newton()` and `JointDoFType.from_newton()`, making the system extensible through pure Python `IntEnum` modifications.

## Frequently Asked Questions

### What is the difference between JointType and JointDoFType in Newton?

`JointType` is the public-facing enumeration defined in [`newton/_src/sim/enums.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/enums.py) that serves as the primary contract for users and external tools like USD Physics or MuJoCo importers. `JointDoFType` is the internal solver representation in [`newton/_src/solvers/kamino/_src/core/joints.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/solvers/kamino/_src/core/joints.py) that encodes mathematical properties including coordinate count, degrees of freedom, and bilateral constraint requirements for the physics solver.

### How do I choose between a Ball joint and a D6 joint in Newton?

Choose a **Ball** joint when you need three rotational degrees of freedom with locked translation, such as for shoulder or hip joints in character animation, as it uses a quaternion representation that avoids gimbal lock. Choose a **D6** joint when you need a configurable combination of specific translational and rotational axes, such as for robotic joints requiring prismatic motion along one axis combined with rotation around another, which the solver internally maps to specialized types like `CYLINDRICAL` or `UNIVERSAL`.

### Where are Newton joint types defined in the source code?

The public `JointType` enumeration is defined in [`newton/_src/sim/enums.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/enums.py) (lines 46-69), while the internal `JointDoFType` enumeration and conversion logic reside in [`newton/_src/solvers/kamino/_src/core/joints.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/solvers/kamino/_src/core/joints.py) (lines 87-124 for DoF definitions, lines 66-80 for the mapping table). The high-level `JointDescriptor` class used to instantiate joints is also located in the [`joints.py`](https://github.com/newton-physics/newton/blob/main/joints.py) file (lines 81-95).

### Can I create custom joint types in Newton?

Yes, the explicit mapping architecture between `JointDoFType` and `JointType` makes the system extensible without hidden magic. To create a custom joint, add a new member to `JointDoFType` with appropriate `num_coords`, `num_dofs`, and `num_cts` values in [`newton/_src/solvers/kamino/_src/core/joints.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/solvers/kamino/_src/core/joints.py), add a corresponding entry in the `_MAP_TO_NEWTON` dictionary (lines 66-80), and optionally expose a new `JointType` value in [`newton/_src/sim/enums.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/enums.py) for external API compatibility.