# How the CAD Viewer Handles URDF Robot Poses and Kinematics: A Technical Deep Dive

> Explore how the CAD Viewer parses URDF, computes forward kinematics, and enables interactive pose manipulation for robots. Learn the technical details of robot pose handling.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: deep-dive
- Published: 2026-08-01

---

**The CAD Viewer processes URDF files by parsing the XML into a JavaScript model, computing forward kinematics through hierarchical transform chains, and enabling interactive pose manipulation via a spherical picker interface.**

The text-to-cad repository includes a sophisticated CAD Viewer that treats URDF robots as hierarchical kinematic chains. Understanding how this viewer handles URDF robot poses and kinematics reveals a three-stage pipeline: XML parsing, transform calculation, and interactive posing with smooth animation.

## Parsing URDF XML into a JavaScript Model

The pipeline begins in [`viewer/packages/cadjs/src/lib/urdf/parseUrdf.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/cadjs/src/lib/urdf/parseUrdf.js), where the raw XML is converted into a plain JavaScript description (`urdfData`). This object contains structured arrays of **links**, **joints**, **visual meshes**, and **material definitions**.

The parser validates the robot tree structure to ensure a single root link and no cyclic dependencies. It returns an object with three primary properties: `links`, `joints`, and `namedMaterialColors`. This normalized representation serves as the foundation for all subsequent kinematic calculations.

## Computing Forward Kinematics and World Transforms

Once parsed, the viewer calculates the spatial relationship between every link using forward kinematics. The core implementation resides in [`viewer/packages/cadjs/src/lib/urdf/kinematics.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/cadjs/src/lib/urdf/kinematics.js), specifically the `solveUrdfLinkWorldTransforms` function.

This function traverses the joint graph from root to children, accumulating transforms through a chain of operations:

- **`translationTransform`** – applies the joint's positional offset
- **`rotationTransformFromRpy`** – applies the joint's orientation (roll, pitch, yaw)
- **`posedJointLocalTransform`** – rotates by the current joint angle (converting degrees to radians)

The module provides essential math utilities including `multiplyTransforms`, `invertRigidTransform`, and `transformPoint` for rigid body operations.

For mesh rendering, `poseUrdfMeshData` takes the raw geometry from URDF `<mesh>` tags and multiplies each vertex by the corresponding link's world transform, producing `THREE.BufferGeometry` ready for the scene.

## Interactive Pose Picking and Joint Animation

User interaction with URDF robot poses happens through a spherical "pose picker" system implemented in [`viewer/packages/cadjs/src/lib/viewer/urdfPosePicker.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/cadjs/src/lib/viewer/urdfPosePicker.js). When a user clicks the model, the viewer:

1. Generates a translucent spherical grid via `resolveUrdfPosePickerShell`
2. Casts a ray from camera NDC coordinates using `intersectUrdfPosePickerShellAtNdc`
3. Maps the intersection point to spherical coordinates with `urdfPosePickerCellForModelPoint`
4. Translates the selected cell into a target joint angle

Animation smoothing is handled by [`viewer/packages/cadjs/src/lib/urdf/jointAnimation.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/cadjs/src/lib/urdf/jointAnimation.js), which exports `URDF_JOINT_ANIMATION_DURATION_MS` for timing and `jointValueMapsClose` for interpolation checks. The UI layer in [`viewer/src/client/components/workbench/UrdfFileSheet.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/workbench/UrdfFileSheet.js) manages joint value state, while [`viewer/src/client/components/CadWorkspace.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/CadWorkspace.js) orchestrates the animation loop.

## Practical Implementation Examples

### Loading a URDF and Computing Kinematic Data

```javascript
import { parseUrdf } from 'cadjs/lib/urdf/parseUrdf.js';
import { solveUrdfLinkWorldTransforms, buildDefaultUrdfJointValues } from 'cadjs/lib/urdf/kinematics.js';

// xmlText contains the URDF file contents
const urdfData = parseUrdf(xmlText);
const defaultJointValues = buildDefaultUrdfJointValues(urdfData);

// Compute world transforms for the default pose
const linkWorldTransforms = solveUrdfLinkWorldTransforms(urdfData, defaultJointValues);

// Access a specific link's 4×4 column-major transform matrix
const baseLinkMatrix = linkWorldTransforms['base_link'];

```

### Using the Spherical Pose Picker

```javascript
import {
  resolveUrdfPosePickerShell,
  intersectUrdfPosePickerShellAtNdc,
  urdfPosePickerCellForModelPoint,
} from 'cadjs/lib/viewer/urdfPosePicker.js';

// runtime contains the THREE scene, camera, and model group
const picker = { center: [0, 0, 0] };
const ndc = { x: mouseNdcX, y: mouseNdcY };

// Find intersection point on the spherical shell
const hit = intersectUrdfPosePickerShellAtNdc(runtime, picker, ndc);
if (hit) {
  // Convert world point to spherical cell coordinates
  const cell = urdfPosePickerCellForModelPoint(runtime, picker, hit.point);
  
  // Map cell to joint angle (example: shoulder joint)
  const angleDeg = (cell.x / URDF_POSE_PICKER_SHELL_WIDTH_SEGMENTS) * 360;
  jointValuesByName['shoulder'] = angleDeg;
}

```

### Animating Joint Value Changes

```javascript
import { jointValueMapsClose, URDF_JOINT_ANIMATION_DURATION_MS } from 'cadjs/lib/urdf/jointAnimation.js';

function animateToPose(targetValues, currentValues) {
  const startTime = performance.now();
  
  const animate = (now) => {
    const t = Math.min((now - startTime) / URDF_JOINT_ANIMATION_DURATION_MS, 1);
    const interpolated = {};
    
    for (const name of Object.keys(targetValues)) {
      const startVal = currentValues[name] || 0;
      const endVal = targetValues[name];
      interpolated[name] = startVal + (endVal - startVal) * t;
    }
    
    updateJointValues(interpolated);
    
    if (!jointValueMapsClose(interpolated, targetValues)) {
      requestAnimationFrame(animate);
    }
  };
  
  requestAnimationFrame(animate);
}

```

## Summary

- **Parse**: [`parseUrdf.js`](https://github.com/earthtojake/text-to-cad/blob/main/parseUrdf.js) converts XML to structured JavaScript objects with validated link/joint hierarchies
- **Transform**: [`kinematics.js`](https://github.com/earthtojake/text-to-cad/blob/main/kinematics.js) computes forward kinematics via `solveUrdfLinkWorldTransforms`, chaining translation, rotation, and joint angle transforms
- **Interact**: [`urdfPosePicker.js`](https://github.com/earthtojake/text-to-cad/blob/main/urdfPosePicker.js) provides spherical ray-casting to map screen coordinates to joint angles
- **Animate**: [`jointAnimation.js`](https://github.com/earthtojake/text-to-cad/blob/main/jointAnimation.js) supplies timing constants and interpolation helpers for smooth pose transitions
- **Orchestrate**: [`CadWorkspace.js`](https://github.com/earthtojake/text-to-cad/blob/main/CadWorkspace.js) and [`UrdfFileSheet.js`](https://github.com/earthtojake/text-to-cad/blob/main/UrdfFileSheet.js) manage state and UI integration

## Frequently Asked Questions

### How does the viewer validate URDF structure during parsing?

The [`parseUrdf.js`](https://github.com/earthtojake/text-to-cad/blob/main/parseUrdf.js) module validates that the robot definition contains a single root link and detects any cyclic dependencies in the joint graph. This ensures the kinematic chain forms a proper tree structure before attempting to solve transforms, preventing infinite loops during the traversal in `solveUrdfLinkWorldTransforms`.

### What coordinate system does the viewer use for URDF transforms?

All transforms are stored as 4×4 column-major matrices in the world coordinate system. The [`kinematics.js`](https://github.com/earthtojake/text-to-cad/blob/main/kinematics.js) file provides `multiplyTransforms` for composition and `invertRigidTransform` for inversion, maintaining consistency with standard 3D graphics conventions used by the underlying THREE.js rendering engine.

### How does the spherical pose picker translate clicks into joint angles?

The system in [`urdfPosePicker.js`](https://github.com/earthtojake/text-to-cad/blob/main/urdfPosePicker.js) creates a spherical shell around the robot model. When a user clicks, `intersectUrdfPosePickerShellAtNdc` performs ray-sphere intersection in normalized device coordinates. The hit point is converted to spherical coordinates via `urdfPosePickerCellForModelPoint`, which maps angular sectors to specific joint values based on the URDF joint limits and axis definitions.

### Which component manages the animation loop for joint movements?

[`viewer/src/client/components/CadWorkspace.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/CadWorkspace.js) drives the animation loop, while [`viewer/src/client/components/workbench/UrdfFileSheet.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/workbench/UrdfFileSheet.js) handles the joint value state management. The actual interpolation logic uses `jointValueMapsClose` from [`jointAnimation.js`](https://github.com/earthtojake/text-to-cad/blob/main/jointAnimation.js) to determine when the current values have reached their targets, using `URDF_JOINT_ANIMATION_DURATION_MS` to define the transition length.