# Industrial Robot Arm

> A stylized industrial robot arm on a bolted pedestal with a fully rigged joint chain: base (yaw), shoulder, elbow and wrist groups pivot exactly at their joint axes, ending in a parallel gripper group with two sliding fingers. Includes motor housings, a cable hose, hazard stripes and a status light. Pose it with the turn, shoulder, elbow and wrist angles — great for factories, labs, sci-fi bases and assembly-line puzzle games.

![Industrial Robot Arm preview](https://codels.download/m/robot-arm.png)

Multi-view sheet (3/4, front, side, top): https://codels.download/m/robot-arm.sheet.png

## Facts

- Category: Sci-Fi › Robots & Drones
- Size (W × H × D): 1.85 × 2.24 × 1.68 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 1,216 · Meshes: 48 · Materials: 5
- License: CC0-1.0 (Codels built-in)
- Tags: machine, robot, robot-arm, low-poly, stylized, industrial, modern, sci-fi, interior, puzzle, hazard, interactable, prop, metal, emissive, game-ready, mobile-friendly, parametric, color-gray, color-orange, size-medium, poly-low
- Page: https://codels.download/models/robot-arm

## Files

| Format | URL |
|---|---|
| three.js ES module (`createRobotArm()`) | https://codels.download/m/robot-arm.js |
| React Three Fiber component (`<RobotArm />`) | https://codels.download/m/robot-arm.jsx |
| Instancing module (`createRobotArmInstances(count, place)`, one draw call per material) | https://codels.download/m/robot-arm.instanced.js |
| Standalone HTML demo | https://codels.download/m/robot-arm.html |
| glTF binary | https://codels.download/m/robot-arm.glb |
| glTF binary, Meshopt-compressed (2–3× smaller; GLTFLoader needs `setMeshoptDecoder(MeshoptDecoder)`) | https://codels.download/m/robot-arm.glb?compress=meshopt |
| glTF JSON | https://codels.download/m/robot-arm.gltf |
| OBJ (vertex colors) + MTL | https://codels.download/m/robot-arm.obj · https://codels.download/m/robot-arm.mtl |
| STL | https://codels.download/m/robot-arm.stl |
| CodelSpec JSON | https://codels.download/m/robot-arm.json |

## Parameters

Append them as query parameters to any URL above to get a customized variant (e.g. `?bodyColor=...`).

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `bodyColor` | color | #rrggbb | #ef8a1f | #ef8a1f |
| `baseTurn` | number | -180 – 180 | -50 | -50 |
| `shoulder` | number | -45 – 60 | 20 | 20 |
| `elbow` | number | 0 – 140 | 95 | 95 |
| `wrist` | number | -120 – 120 | 65 | 65 |

## Parts

- pedestal (group)
  - floorPlate (cylinder · dark)
  - pedestalBody (cylinder · dark)
  - bolt (cylinder · metal)
  - bolt (cylinder · metal)
  - bolt (cylinder · metal)
  - bolt (cylinder · metal)
  - bolt (cylinder · metal)
  - bolt (cylinder · metal)
  - bolt (cylinder · metal)
  - bolt (cylinder · metal)
  - hazardTile (box · dark)
  - hazardTile (box · warn)
  - hazardTile (box · dark)
  - hazardTile (box · warn)
  - hazardTile (box · dark)
  - hazardTile (box · warn)
  - hazardTile (box · dark)
  - hazardTile (box · warn)
  - hazardTile (box · dark)
  - hazardTile (box · warn)
  - hazardTile (box · dark)
  - hazardTile (box · warn)
- base (group)
  - turntable (cylinder · body)
  - turntableRing (cylinder · dark)
  - yokePlate (box · body)
  - yokePlate (box · body)
  - baseMotor (box · dark)
  - statusLight (sphere · glow)
  - shoulder (group)
    - shoulderJoint (cylinder · dark)
    - shoulderCap (cylinder · metal)
    - upperArm (box · body)
    - upperArmPanel (box · dark)
    - shoulderMotor (cylinder · dark)
    - cableHose (tube · dark)
    - elbow (group)
      - elbowJoint (cylinder · dark)
      - elbowCap (cylinder · metal)

## How to use

Save the code below as `robot-arm.js`, then:

```js
import { createRobotArm } from './robot-arm.js';
const model = createRobotArm();
scene.add(model);
```

## Code

```js
/**
 * Industrial Robot Arm — Codels 3D model library (https://codels.download/models/robot-arm)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,216 · Size (W × H × D): 1.85 × 2.24 × 1.68 m
 *
 * Usage:
 *   import { createRobotArm } from './robot-arm.js';
 *   
 *   const model = createRobotArm();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Tube along a smooth curve through the given points.
function tube(path, radius, tubularSegments, radialSegments, closed = false) {
  const curve = new THREE.CatmullRomCurve3(path.map(([x, y, z]) => new THREE.Vector3(x, y, z)), closed);
  return new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
}

export function createRobotArm() {
  const root = new THREE.Group();
  root.name = 'RobotArm';

  // Materials
  const bodyMat = new THREE.MeshStandardMaterial({ name: 'body', color: 0xef8a1f, roughness: 0.45, metalness: 0.2, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x2f3237, roughness: 0.6, metalness: 0.4, flatShading: true });
  const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0xa6acb4, roughness: 0.3, metalness: 0.8, flatShading: true });
  const warnMat = new THREE.MeshStandardMaterial({ name: 'warn', color: 0xe9c23a, roughness: 0.5, flatShading: true });
  const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x5dff8a, roughness: 0.4, emissive: 0x2eff66, emissiveIntensity: 1.4, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.035, 0.035, 0.05, 6);
  const boxGeo = new THREE.BoxGeometry(0.13, 0.1, 0.03);
  const boxGeo2 = new THREE.BoxGeometry(0.1, 0.62, 0.5);
  const boxGeo3 = new THREE.BoxGeometry(0.05, 0.2, 0.1);
  const boxGeo4 = new THREE.BoxGeometry(0.02, 0.12, 0.09);

  // Parts
  const pedestal = new THREE.Group();
  pedestal.name = 'pedestal';
  root.add(pedestal);
  const floorPlate = new THREE.Mesh(new THREE.CylinderGeometry(0.55, 0.6, 0.08, 16), darkMat);
  floorPlate.name = 'floorPlate';
  floorPlate.position.set(0, 0.04, 0);
  pedestal.add(floorPlate);
  const pedestalBody = new THREE.Mesh(new THREE.CylinderGeometry(0.42, 0.46, 0.28, 12), darkMat);
  pedestalBody.name = 'pedestalBody';
  pedestalBody.position.set(0, 0.22, 0);
  pedestal.add(pedestalBody);
  const bolt = new THREE.Mesh(cylinderGeo, metalMat);
  bolt.name = 'bolt';
  bolt.position.set(0.199, 0.105, 0.4804);
  pedestal.add(bolt);
  const bolt2 = new THREE.Mesh(cylinderGeo, metalMat);
  bolt2.name = 'bolt';
  bolt2.position.set(0.4804, 0.105, 0.199);
  pedestal.add(bolt2);
  const bolt3 = new THREE.Mesh(cylinderGeo, metalMat);
  bolt3.name = 'bolt';
  bolt3.position.set(0.4804, 0.105, -0.199);
  pedestal.add(bolt3);
  const bolt4 = new THREE.Mesh(cylinderGeo, metalMat);
  bolt4.name = 'bolt';
  bolt4.position.set(0.199, 0.105, -0.4804);
  pedestal.add(bolt4);
  const bolt5 = new THREE.Mesh(cylinderGeo, metalMat);
  bolt5.name = 'bolt';
  bolt5.position.set(-0.199, 0.105, -0.4804);
  pedestal.add(bolt5);
  const bolt6 = new THREE.Mesh(cylinderGeo, metalMat);
  bolt6.name = 'bolt';
  bolt6.position.set(-0.4804, 0.105, -0.199);
  pedestal.add(bolt6);
  const bolt7 = new THREE.Mesh(cylinderGeo, metalMat);
  bolt7.name = 'bolt';
  bolt7.position.set(-0.4804, 0.105, 0.199);
  pedestal.add(bolt7);
  const bolt8 = new THREE.Mesh(cylinderGeo, metalMat);
  bolt8.name = 'bolt';
  bolt8.position.set(-0.199, 0.105, 0.4804);
  pedestal.add(bolt8);
  const hazardTile = new THREE.Mesh(boxGeo, darkMat);
  hazardTile.name = 'hazardTile';
  hazardTile.position.set(0, 0.22, 0.45);
  pedestal.add(hazardTile);
  const hazardTile2 = new THREE.Mesh(boxGeo, warnMat);
  hazardTile2.name = 'hazardTile';
  hazardTile2.position.set(0.225, 0.22, 0.3897);
  hazardTile2.rotation.set(0, deg(30), 0);
  pedestal.add(hazardTile2);
  const hazardTile3 = new THREE.Mesh(boxGeo, darkMat);
  hazardTile3.name = 'hazardTile';
  hazardTile3.position.set(0.3897, 0.22, 0.225);
  hazardTile3.rotation.set(0, deg(60), 0);
  pedestal.add(hazardTile3);
  const hazardTile4 = new THREE.Mesh(boxGeo, warnMat);
  hazardTile4.name = 'hazardTile';
  hazardTile4.position.set(0.45, 0.22, 0);
  hazardTile4.rotation.set(0, deg(90), 0);
  pedestal.add(hazardTile4);
  const hazardTile5 = new THREE.Mesh(boxGeo, darkMat);
  hazardTile5.name = 'hazardTile';
  hazardTile5.position.set(0.3897, 0.22, -0.225);
  hazardTile5.rotation.set(0, deg(120), 0);
  pedestal.add(hazardTile5);
  const hazardTile6 = new THREE.Mesh(boxGeo, warnMat);
  hazardTile6.name = 'hazardTile';
  hazardTile6.position.set(0.225, 0.22, -0.3897);
  hazardTile6.rotation.set(0, deg(150), 0);
  pedestal.add(hazardTile6);
  const hazardTile7 = new THREE.Mesh(boxGeo, darkMat);
  hazardTile7.name = 'hazardTile';
  hazardTile7.position.set(0, 0.22, -0.45);
  hazardTile7.rotation.set(0, deg(180), 0);
  pedestal.add(hazardTile7);
  const hazardTile8 = new THREE.Mesh(boxGeo, warnMat);
  hazardTile8.name = 'hazardTile';
  hazardTile8.position.set(-0.225, 0.22, -0.3897);
  hazardTile8.rotation.set(0, deg(210), 0);
  pedestal.add(hazardTile8);
  const hazardTile9 = new THREE.Mesh(boxGeo, darkMat);
  hazardTile9.name = 'hazardTile';
  hazardTile9.position.set(-0.3897, 0.22, -0.225);
  hazardTile9.rotation.set(0, deg(240), 0);
  pedestal.add(hazardTile9);
  const hazardTile10 = new THREE.Mesh(boxGeo, warnMat);
  hazardTile10.name = 'hazardTile';
  hazardTile10.position.set(-0.45, 0.22, 0);
  hazardTile10.rotation.set(0, deg(270), 0);
  pedestal.add(hazardTile10);
  const hazardTile11 = new THREE.Mesh(boxGeo, darkMat);
  hazardTile11.name = 'hazardTile';
  hazardTile11.position.set(-0.3897, 0.22, 0.225);
  hazardTile11.rotation.set(0, deg(300), 0);
  pedestal.add(hazardTile11);
  const hazardTile12 = new THREE.Mesh(boxGeo, warnMat);
  hazardTile12.name = 'hazardTile';
  hazardTile12.position.set(-0.225, 0.22, 0.3897);
  hazardTile12.rotation.set(0, deg(330), 0);
  pedestal.add(hazardTile12);
  const base = new THREE.Group();
  base.name = 'base';
  base.position.set(0, 0.36, 0);
  base.rotation.set(0, deg(-50), 0);
  root.add(base);
  const turntable = new THREE.Mesh(new THREE.CylinderGeometry(0.4, 0.42, 0.22, 14), bodyMat);
  turntable.name = 'turntable';
  turntable.position.set(0, 0.11, 0);
  base.add(turntable);
  const turntableRing = new THREE.Mesh(new THREE.CylinderGeometry(0.36, 0.36, 0.04, 14), darkMat);
  turntableRing.name = 'turntableRing';
  turntableRing.position.set(0, 0.24, 0);
  base.add(turntableRing);
  const yokePlate = new THREE.Mesh(boxGeo2, bodyMat);
  yokePlate.name = 'yokePlate';
  yokePlate.position.set(0.26, 0.51, 0.14);
  base.add(yokePlate);
  const yokePlate2 = new THREE.Mesh(boxGeo2, bodyMat);
  yokePlate2.name = 'yokePlate';
  yokePlate2.position.set(-0.26, 0.51, 0.14);
  base.add(yokePlate2);
  const baseMotor = new THREE.Mesh(new THREE.BoxGeometry(0.32, 0.36, 0.36), darkMat);
  baseMotor.name = 'baseMotor';
  baseMotor.position.set(0, 0.38, -0.22);
  base.add(baseMotor);
  const statusLight = new THREE.Mesh(new THREE.SphereGeometry(0.04, 6, 4), glowMat);
  statusLight.name = 'statusLight';
  statusLight.position.set(0.17, 0.48, -0.22);
  base.add(statusLight);
  const shoulder = new THREE.Group();
  shoulder.name = 'shoulder';
  shoulder.position.set(0, 0.52, 0.14);
  shoulder.rotation.set(deg(20), 0, 0);
  base.add(shoulder);
  const shoulderJoint = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.2, 0.5, 12), darkMat);
  shoulderJoint.name = 'shoulderJoint';
  shoulderJoint.rotation.set(0, 0, deg(90));
  shoulder.add(shoulderJoint);
  const shoulderCap = new THREE.Mesh(new THREE.CylinderGeometry(0.14, 0.14, 0.7, 10), metalMat);
  shoulderCap.name = 'shoulderCap';
  shoulderCap.rotation.set(0, 0, deg(90));
  shoulder.add(shoulderCap);
  const upperArm = new THREE.Mesh(new THREE.BoxGeometry(0.3, 1, 0.34), bodyMat);
  upperArm.name = 'upperArm';
  upperArm.position.set(0, 0.55, 0);
  shoulder.add(upperArm);
  const upperArmPanel = new THREE.Mesh(new THREE.BoxGeometry(0.32, 0.5, 0.06), darkMat);
  upperArmPanel.name = 'upperArmPanel';
  upperArmPanel.position.set(0, 0.495, 0.18);
  shoulder.add(upperArmPanel);
  const shoulderMotor = new THREE.Mesh(new THREE.CylinderGeometry(0.13, 0.13, 0.42, 10), darkMat);
  shoulderMotor.name = 'shoulderMotor';
  shoulderMotor.position.set(0, 0.05, -0.2);
  shoulderMotor.rotation.set(0, 0, deg(90));
  shoulder.add(shoulderMotor);
  const cableHose = new THREE.Mesh(tube([[0.18, 0.15, -0.12], [0.24, 0.55, -0.18], [0.18, 0.98, -0.12]], 0.035, 8, 5), darkMat);
  cableHose.name = 'cableHose';
  shoulder.add(cableHose);
  const elbow = new THREE.Group();
  elbow.name = 'elbow';
  elbow.position.set(0, 1.1, 0);
  elbow.rotation.set(deg(95), 0, 0);
  shoulder.add(elbow);
  const elbowJoint = new THREE.Mesh(new THREE.CylinderGeometry(0.16, 0.16, 0.42, 12), darkMat);
  elbowJoint.name = 'elbowJoint';
  elbowJoint.rotation.set(0, 0, deg(90));
  elbow.add(elbowJoint);
  const elbowCap = new THREE.Mesh(new THREE.CylinderGeometry(0.11, 0.11, 0.46, 10), metalMat);
  elbowCap.name = 'elbowCap';
  elbowCap.rotation.set(0, 0, deg(90));
  elbow.add(elbowCap);
  const elbowHousing = new THREE.Mesh(new THREE.BoxGeometry(0.26, 0.3, 0.32), bodyMat);
  elbowHousing.name = 'elbowHousing';
  elbowHousing.position.set(0, -0.12, 0);
  elbow.add(elbowHousing);
  const counterweight = new THREE.Mesh(new THREE.BoxGeometry(0.22, 0.32, 0.3), darkMat);
  counterweight.name = 'counterweight';
  counterweight.position.set(0, -0.3, 0);
  elbow.add(counterweight);
  const forearm = new THREE.Mesh(new THREE.CylinderGeometry(0.11, 0.14, 0.85, 10), bodyMat);
  forearm.name = 'forearm';
  forearm.position.set(0, 0.5, 0);
  elbow.add(forearm);
  const forearmBand = new THREE.Mesh(new THREE.BoxGeometry(0.24, 0.05, 0.3), warnMat);
  forearmBand.name = 'forearmBand';
  forearmBand.position.set(0, 0.62, 0);
  elbow.add(forearmBand);
  const wrist = new THREE.Group();
  wrist.name = 'wrist';
  wrist.position.set(0, 1, 0);
  wrist.rotation.set(deg(65), 0, 0);
  elbow.add(wrist);
  const wristJoint = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.1, 0.26, 10), darkMat);
  wristJoint.name = 'wristJoint';
  wristJoint.rotation.set(0, 0, deg(90));
  wrist.add(wristJoint);
  const wristBody = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.08, 0.16, 10), bodyMat);
  wristBody.name = 'wristBody';
  wristBody.position.set(0, 0.14, 0);
  wrist.add(wristBody);
  const toolFlange = new THREE.Mesh(new THREE.CylinderGeometry(0.11, 0.11, 0.04, 12), metalMat);
  toolFlange.name = 'toolFlange';
  toolFlange.position.set(0, 0.24, 0);
  wrist.add(toolFlange);
  const gripper = new THREE.Group();
  gripper.name = 'gripper';
  gripper.position.set(0, 0.26, 0);
  wrist.add(gripper);
  const palm = new THREE.Mesh(new THREE.BoxGeometry(0.3, 0.08, 0.14), darkMat);
  palm.name = 'palm';
  palm.position.set(0, 0.04, 0);
  gripper.add(palm);
  const fingerL = new THREE.Group();
  fingerL.name = 'fingerL';
  fingerL.position.set(0.09, 0.08, 0);
  gripper.add(fingerL);
  const finger = new THREE.Mesh(boxGeo3, metalMat);
  finger.name = 'finger';
  finger.position.set(0, 0.1, 0);
  fingerL.add(finger);
  const fingerPad = new THREE.Mesh(boxGeo4, darkMat);
  fingerPad.name = 'fingerPad';
  fingerPad.position.set(-0.035, 0.12, 0);
  fingerL.add(fingerPad);
  const fingerR = new THREE.Group();
  fingerR.name = 'fingerR';
  fingerR.position.set(-0.09, 0.08, 0);
  gripper.add(fingerR);
  const finger2 = new THREE.Mesh(boxGeo3, metalMat);
  finger2.name = 'finger';
  finger2.position.set(0, 0.1, 0);
  fingerR.add(finger2);
  const fingerPad2 = new THREE.Mesh(boxGeo4, darkMat);
  fingerPad2.name = 'fingerPad';
  fingerPad2.position.set(0.035, 0.12, 0);
  fingerR.add(fingerPad2);

  root.traverse((o) => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });
  return root;
}

export default createRobotArm;
```

---
Codels — 3D models as code for three.js. Search more: https://codels.download/api/v1/models?q=<query> · Guide: https://codels.download/llms.txt
