# Generalized vs Maximal Coordinates in Newton Solvers: What's the Difference?

> Understand generalized vs maximal coordinates in Newton solvers. Generalized coordinates use joint-space variables, while maximal coordinates store 6-DOF body states directly, removing forward kinematics.

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

---

**Generalized coordinates use joint-space variables that require forward kinematics to derive body poses, while maximal coordinates store full 6-DOF body states directly in world space, eliminating the need for forward kinematics passes.**

The Newton physics engine provides two distinct coordinate representations for rigid-body dynamics, each optimized for different simulation scenarios. Understanding whether a solver uses generalized (articulation) or maximal (world-space) coordinates is essential for correctly initializing states, handling collisions, and optimizing performance.

## What Are Generalized Coordinates?

Generalized coordinates represent articulated systems through a reduced set of variables corresponding to joint degrees of freedom (DOF) rather than individual body poses. In this representation, the state vector contains only the independent variables needed to describe the mechanism's configuration.

### Implementation in Newton

In [`newton/solvers.py`](https://github.com/newton-physics/newton/blob/main/newton/solvers.py), generalized-coordinate solvers operate on `joint_q` (joint positions) and `joint_qd` (joint velocities) as the primary state variables. Rigid-body poses (`body_q` and `body_qd`) are derived quantities computed via forward kinematics (FK) each simulation step.

According to the solver capabilities table in [`newton/solvers.py`](https://github.com/newton-physics/newton/blob/main/newton/solvers.py) (lines 64-66), generalized-coordinate support is explicitly marked for Featherstone and MuJoCo solvers.

### Solver Types Using Generalized Coordinates

- **SolverFeatherstone**: Implements articulated-body algorithms using reduced coordinates
- **SolverMuJoCo**: Wraps MuJoCo's native generalized-coordinate dynamics

## What Are Maximal Coordinates?

Maximal coordinates represent each rigid body independently using its full 6-DOF pose in world space, regardless of joint constraints. This approach stores the complete transformation for every body, treating joints as constraints between these independent bodies rather than as the primary coordinate variables.

### Implementation in Newton

Maximal-coordinate solvers in Newton store state directly in `body_q` (body poses) and `body_qd` (body twists). As documented in [`newton/solvers.py`](https://github.com/newton-physics/newton/blob/main/newton/solvers.py) (lines 81-84), these solvers include XPBD, Semi-Implicit, Kamino, and VBD implementations.

Because body variables already contain the world-space pose, no forward kinematics pass is required to obtain body positions for collision detection or constraint resolution.

### Solver Types Using Maximal Coordinates

- **SolverXPBD**: Extended Position-Based Dynamics using maximal coordinates
- **SolverSemiImplicit**: Semi-implicit Euler integration with world-space bodies
- **SolverKamino**: Specialized for deformable and rigid coupling
- **SolverVBD**: Velocity-Based Dynamics solver

## Key Differences Between Generalized and Maximal Coordinates

The choice between coordinate representations affects memory layout, computational cost, and constraint handling:

| Aspect | Generalized Coordinates | Maximal Coordinates |
|--------|------------------------|---------------------|
| **State variables** | `joint_q`, `joint_qd` (reduced DOFs) | `body_q`, `body_qd` (6 DOF per body) |
| **Forward kinematics** | Required each step to derive `body_q` | Not required; poses stored directly |
| **Linear system size** | Smaller (joint count) | Larger (body count × 6) |
| **Joint limits** | Simple bounds on `joint_q` | Constraint equations between bodies |
| **Collision handling** | Computed after FK; contacts external to solver | Integrated into solver constraints |
| **Numerical drift** | Potential drift in body velocity conversion | Direct integration, tighter precision |

As noted in [`newton/tests/test_body_velocity.py`](https://github.com/newton-physics/newton/blob/main/newton/tests/test_body_velocity.py), generalized-coordinate solvers require calling `eval_fk` after setting `joint_qd` to propagate velocities to body space (lines 24-26), while maximal-coordinate solvers write directly to `body_qd` (lines 13-15).

## How to Detect Coordinate Type in Code

The test suite in [`newton/tests/test_kinematic_links.py`](https://github.com/newton-physics/newton/blob/main/newton/tests/test_kinematic_links.py) provides a helper pattern (lines 84-86) to determine if a solver uses maximal coordinates by checking its type against the maximal-coordinate solver classes.

```python
import newton

def is_maximal(solver: newton.solvers.SolverBase) -> bool:
    """Return True if the solver works on maximal (world‑space) coordinates."""
    # Mirrors the test helper _uses_maximal_coordinates

    return isinstance(
        solver,
        newton.solvers.SolverXPBD
        | newton.solvers.SolverSemiImplicit
        | newton.solvers.SolverVBD,
    )

```

## Setting Initial Velocities Correctly

The initialization pattern differs based on coordinate representation. The following example from the Newton test patterns shows how to set body velocities for both solver types:

```python
import newton
import warp as wp
import numpy as np

def set_initial_velocity(state, solver, vel_body):
    """Set angular+linear velocity for a single free body.
    
    * `vel_body` – 6‑element array [lin_x, lin_y, lin_z, ang_x, ang_y, ang_z].
    * For generalized solvers we set `joint_qd` and run FK.
    * For maximal solvers we set `body_qd` directly.
    """
    vel = np.asarray(vel_body, dtype=np.float32).reshape(1, 6)

    if is_maximal(solver):
        # Maximal‑coordinate solvers (XPBD, SemiImplicit, VBD)

        state.body_qd.assign(vel)                # body‑space twist

    else:
        # Generalized‑coordinate solvers (MuJoCo, Featherstone)

        state.joint_qd.assign(vel)               # joint‑space twist

        # Propagate to body space so the solver sees a consistent pose

        newton.eval_fk(state.model, state.joint_q, state.joint_qd, state)

```

## Choosing the Right Solver for Your Simulation

Select your coordinate representation based on the dominant physics in your scene:

**Use generalized coordinates** (`SolverFeatherstone`, `SolverMuJoCo`) when:
- Your simulation is dominated by articulated mechanisms (robot arms, humanoids, kinematic chains)
- You need the smallest possible linear system for performance
- Joint limits and motor constraints are the primary concern
- You can afford the forward kinematics overhead each step

**Use maximal coordinates** (`SolverXPBD`, `SolverSemiImplicit`, `SolverKamino`, `SolverVBD`) when:
- Your simulation involves many contacts, collisions, or soft-body coupling
- You need to handle both articulated and free bodies with the same solver
- You want to avoid numerical drift from FK conversions
- You prefer direct integration of body twists for sub-microsecond precision

## Summary

- **Generalized coordinates** store state in `joint_q` and `joint_qd`, requiring `eval_fk` to derive body poses, and are used by `SolverFeatherstone` and `SolverMuJoCo`.
- **Maximal coordinates** store full 6-DOF poses in `body_q` and `body_qd`, need no forward kinematics, and are used by `SolverXPBD`, `SolverSemiImplicit`, `SolverKamino`, and `SolverVBD`.
- The coordinate type determines how you initialize velocities: use `joint_qd` + `eval_fk` for generalized, `body_qd` directly for maximal.
- Choose generalized coordinates for pure articulation dynamics with minimal DOFs, and maximal coordinates for contact-rich simulations requiring unified body handling.

## Frequently Asked Questions

### Which is faster, generalized or maximal coordinates?

Generalized coordinates typically yield smaller linear systems and faster articulation dynamics because they only solve for joint DOFs rather than 6 DOF per body. However, maximal coordinates eliminate the forward kinematics overhead and handle contacts more efficiently within the solver loop. For robot arms with few contacts, generalized coordinates are usually faster; for debris simulations or character ragdolls with many collisions, maximal coordinates often perform better.

### Can I switch between coordinate types mid-simulation?

No, the coordinate representation is determined by the solver class you instantiate at initialization. `SolverFeatherstone` and `SolverMuJoCo` always use generalized coordinates, while `SolverXPBD` and others always use maximal coordinates. To change representations, you must create a new solver instance and reinitialize the state variables (`joint_q` vs `body_q`).

### Do maximal coordinate solvers handle joint limits?

Yes, but they implement joint limits as constraints between bodies rather than simple bounds on coordinate variables. In generalized coordinates, joint limits are direct bounds on `joint_q` values. In maximal coordinates, the solver adds constraint equations to the linear system to enforce joint limits, which increases system size but allows for more complex limit geometries and coupling effects.

### Why does Newton require eval_fk for generalized solvers?

Generalized solvers operate on `joint_q` and `joint_qd` as the canonical state, but collision detection and rendering require world-space body poses (`body_q`). The `newton.eval_fk` function computes these derived poses via forward kinematics. This call is required after setting joint velocities and before stepping the solver to ensure body-space quantities remain consistent with the joint-space source of truth, as demonstrated in [`newton/tests/test_body_velocity.py`](https://github.com/newton-physics/newton/blob/main/newton/tests/test_body_velocity.py).