Skip to main content

Gear relation

A relation couples two joints: turn one and the other turns with it, by a ratio. A gear relation ties the rotations of two revolute (or cylindrical) mates — meshing gears, a belt drive, a pulley pair. A rack and pinion relation ties a rotation to the travel of a slider (or cylindrical) mate. The joints keep their own freedom: drag either part, or animate either joint, and both move.

RelationMate AMate BRatio
Gearrevolute or cylindricalrevolute or cylindricalturns of B per turn of A
Rack and pinionrevolute or cylindrical (the pinion)slider or cylindrical (the rack)travel of B per turn of A

In the viewport​

  1. Mate each gear to its axle with a Revolute mate first — a relation couples existing joints.
  2. Click Gear on the assembly toolbar (or Rack for a rack and pinion). The Joints panel switches to picking: click the first joint's row, then the second's. Clicking a part in the viewport offers the joints on that part instead.
  3. Set the Ratio — how many turns the second joint makes per turn of the first. Two external gears on parallel axes turn opposite ways, so tick Reverse for a meshing pair.
  4. Drag a gear while the dialog is open: the other one turns with it. Click Apply. The relation gets its own row in the Joints panel, under the joints it couples.

A 12-tooth pinion and a 24-tooth wheel on the base plate, coupled 2:1

The code behind it

Both mates are bound to a const so the relation can name them. The axles are assembly connectors placed on the plate's top face; the gears' bore frames face down to meet them. The ratio is the pinion's tooth count over the wheel's:

gear.part.js
gear.part.js
import { part, param, sketch, line, circle, extrude, cut, repeat, color, plane, connector } from 'fluidcad/core';
import { coincident, distance, fix, horizontal, vertical } from 'fluidcad/constraints';

// A spur gear, 3 mm module: the pitch radius is 1.5 × the tooth count.
// A disc with a Ø8 bore, teeth cut as evenly spaced notches around the rim.
export const gear = part('Gear', () => {
const teeth = param('teeth', 12, 'number', { min: 8, max: 48, step: 1 });
const pitchRadius = teeth * 1.5;
sketch('xy', () => {
// circle() takes a diameter: the blank reaches 3 mm past the pitch
// circle, and the bore is Ø8.
circle([0, 0], 2 * (pitchRadius + 3));
circle([0, 0], 8);
});
const disc = extrude(8);
// One notch at the rim — a 5.5 × 3 mm slot straddling the pitch circle,
// drawn on the top face and cut down through the disc — repeated around
// the axis, once per tooth.
sketch(disc.endFaces(), () => {
const b = line([pitchRadius - 1.5, -1.5], [pitchRadius + 4, -1.5]);
const r = line([pitchRadius + 4, -1.5], [pitchRadius + 4, 1.5]);
const t = line([pitchRadius + 4, 1.5], [pitchRadius - 1.5, 1.5]);
const l = line([pitchRadius - 1.5, 1.5], [pitchRadius - 1.5, -1.5]);
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
horizontal(b);
horizontal(t);
vertical(r);
vertical(l);
fix(b.start(), [pitchRadius - 1.5, -1.5]);
distance(b.start(), b.end(), 5.5);
distance(r.start(), r.end(), 3);
});
cut(8);
repeat('circular', 'z', { count: teeth, angle: 360 });
color('steelblue');

// The bore frame on the underside: Z out of the bottom face, ready to
// meet an axle frame that points up.
connector('bore', plane('-xy'));
});
gear-train.assembly.js
import { assembly, insert, mate, relation, connector } from 'fluidcad/core';
import { plate } from './asm-plate.part.js';
import { gear } from './asm-gear.part.js';

export const gearTrain = assembly('gear-train', () => {
const base = insert(plate).grounded();
// A 12-tooth pinion driving a 24-tooth wheel, 54 mm apart (the sum of
// their pitch radii, 18 + 36).
const pinion = insert(gear, { teeth: 12 }).translate(-27, 0, 10);
const wheel = insert(gear, { teeth: 24 }).translate(27, 0, 10);

// Two axle frames on the plate's top face, as assembly connectors.
const axle1 = connector('axle1', [-27, 0, 10]);
const axle2 = connector('axle2', [27, 0, 10]);
const pinionAxle = mate('revolute', axle1, pinion.connectors.bore);
const wheelAxle = mate('revolute', axle2, wheel.connectors.bore);

// The gear relation: the wheel makes half a turn per pinion turn, and
// turns the other way — external gears on parallel axes counter-rotate.
relation('gear', pinionAxle, wheelAxle, 0.5).reverse();
});

Options​

relation('gear', pinionAxle, wheelAxle, 0.5)
.reverse() // the wheel turns against the pinion's sense
.name('drive') // a stable name, unique within the assembly

// A rack: 20 mm pitch radius → 2π·20 ≈ 125.66 mm of travel per pinion turn.
relation('rack-and-pinion', pinionAxle, rackSlide, 125.66);

How the coupling works​

Each rotation is measured about its own mate's Z axis, each travel along it, so the sign depends on how the connectors point: a positive ratio moves the second joint in the same sense as the first, Reverse the opposite. The relation holds from wherever the parts stand when it is first solved — the file's poses set the mesh phase. Rotate a gear's insert() to re-phase the teeth.

A planar mate frees two directions and a spin, so it has no single travel to couple: put a rack on a slider mate. When a solve cannot hold the ratio — one of the coupled joints is held by another mate, say — the relation's row shows a red dot.