Travel#
Parts that move: slides, hinges, and screws swept as a clearance check
Names: travel body pivot
When to use#
Use it when a part is meant to move and you want the compiler to prove it can: a drawer on its
slides, a door or lid on its hinges, a vise chop on its screw. A travel does not move
anything in the drawing or change a cut: the document is drawn at rest and every part keeps
its one transform. The viewer shows a slider per travel that poses the parts for a look (a view, never the cut list). It adds a check, which carries the moving body through its range and fails
if it meets any other part on the way.
If you only need the hardware counted or recessed, use hardware_mount / hardware_use
(hardware-mounting). A part that is fixed in a different position (a
drawer drawn half open) is just placed there.
Keywords: slide, drawer, runner, hinge, swing, door, lid, vise, screw, travel, sweep, clearance, open, extension, pivot, collision.
Syntax#
A travel is the one child a join may have. The male end of the join moves; the female is
the part it is carried on.
join joint=<Joint> male=Part@Mark female=Part@Mark {
travel [kind=slide|angle] axis=x|y|z|-x|-y|-z [min=<n>] [max=<n>] [rest=<n>] [step=<n>]
[body=part|assembly] [pivot=<Mark>]
}
| Property | Meaning | Default |
|---|---|---|
kind | slide moves along the axis (mm); angle turns about it (degrees, right-handed) | slide |
axis | x, y or z, signed to reverse (-y), in the frame of the assembly the join is written in | required |
min, max | the limits, CEL numbers | min 0; max the item's travel_distance (slide) or max_angle (angle), else an error |
rest | the pose the document is drawn in; must lie in [min, max] | min |
step | sweep spacing | 10 mm for a slide, 5 degrees for an angle |
body | part moves the male part alone; assembly moves every part under its innermost enclosing assembly | part |
pivot | angle only: a mark on the male part the axis passes through | the male end's own mark |
Catalogue numbers a travel reads, on the hardware item the joinery names: travel_distance
(a slide's reach), max_angle (a hinge's swing), and mount_gap, the gap a slide fills between
the two parts it joins. With a mount_gap the check also measures the real gap and fails
(ww::check::slide_clearance) if it is more than 0.5 mm from the catalogue's; the margin is
printed by ww check and is in its JSON (invariants.travel.slide_margins).
Example#
project name="Lidded box" units=mm schema_version=1 {
materials {
material Oak type=hardwood
hardware Hinge leaf_length=50.0 leaf_width=16.0 leaf_thickness=2.0 max_angle=110.0
}
joinery hardware_mount name=LidHinge { hardware Hinge }
assembly Box {
part Case {
stock Oak 100.0 60.0 20.0
mark Seat x=0.0 y=60.0 z=0.0 normal=pos_z
by top_sw
pos x=0.0 y=0.0 z=0.0
}
assembly Lid {
part Panel {
stock Oak 100.0 60.0 10.0
mark Seat x=0.0 y=60.0 z=-10.0 normal=neg_z
// the hinge pin's line: the lid's back edge, on its underside
mark Pin x=0.0 y=60.0 z=-10.0 normal=neg_z
by top_sw
pos x=0.0 y=0.0 z=10.0
}
part Cleat {
stock Oak 100.0 10.0 10.0
by top_sw
pos x=0.0 y=0.0 z=0.0
}
// Swings the whole lid (both parts) up to the hinge's 110 degrees.
join joint=LidHinge male=Panel@Seat female=Case@Seat {
travel kind=angle axis=x body=assembly pivot=Pin
}
}
}
}
A drawer on slides, from examples/welsh_dresser.kdl: the drawer is its own assembly, each
side stands on a slide over its runner, and the catalogue gives the reach and the gap:
hardware UndermountSlide_350 travel_distance=300.0 mount_gap=12.0 load_kg=35.0 ...
join joint=DrawerSlide male=DrawerSide_L@Slide female=Runner_L@SlideEdgeL {
travel axis=-y body=assembly
}
Pitfalls and diagnostics#
- Which end moves. The male end.
body=part(the default) moves that one part, which is right for a vise chop and wrong for a door: writebody=assemblyand put the door's parts in anassembly. A drawer is the same: wrap the front, sides, back and bottom in one. - A join can only name parts of its own assembly or one enclosing it, so the slide joins of
a drawer live in the drawer's assembly and reach out to the runner; the drawer must be a
nested inline
assembly, notpart X instance=. - Two joins, one body. Two hinges on one door each carry the same
travel; it is swept once. Declare it on both so either can be deleted. - Where the pin is matters. The axis passes through the
pivotmark, or the male end's own mark. A hinge mark in the middle of a door's edge puts the pin in the middle of its thickness and the door's back corner swings into the carcass; mark the pin on the show face (welsh_dresser.kdl'sPin_Front/Pin_Back). ww::check::travel_foul(defect): a moving part overlaps a fixed one. The message names both parts, the first sampled travel that fouls, and the onset between that sample and the last clean one. A pair already overlapping atrestisww clash's finding and is skipped.ww::check::travel_invalid(defect): the body moves nothing,minis abovemax,restis outside the range, the pivot mark does not exist, or there is nomaxto default.ww::check::slide_clearance(defect): the gap a slide fills is not itsmount_gap.ww::check::travel_unchecked(defect): the kernel could not intersect a pair; it is not reported clean.ww::expand::bad_travel(error): an unknown property, axis, kind or body word, a missingaxis=, orpivot=on a slide.- Sampling is not a proof. An obstacle thinner than
stepbetween two samples is missed; shrinkstep=. The default (10 mm, 5 degrees) is below every board in the library. - Hardware is never swept. A screw, garter, guide, hinge or slide is a catalogue item and a display proxy, never a part, so it cannot foul anything. Model what must be checked as a part.
- No dynamics. No forces, wear, springs, door sag or thread geometry (ADR-0075).
- The viewer does not yet have a slider per movable part (#225); the data (axis, limits, rest, moving
part ids) is in
PlacedJoin::travel.
See also#
docs/adr/0075-travel-primitive.md;docs/rfc/0081-vise-and-moving-hardware.md,docs/rfc/0050-drawer-runners-and-slides.md,docs/rfc/0071-hardware-hinges.mddocs/KDL_AUTHORING.md§5 (hardware) and §8 (join)examples/workbench.kdl(a vise chop, 0 to 180 mm),examples/welsh_dresser.kdl(slides and door swings),examples/blanket_chest.kdl(a lid swung 100 degrees)hardware-mounting,joinery-contract
Names#
Every name this page declares, how the example library uses it, and the shortest real use.
travel#
node in 3 of 116 examples (8 uses).
Shortest real use, from welsh_dresser.kdl:
travel axis=-y body=assembly
body#
word-valued property; property in 2 of 116 examples (7 uses).
Shortest real use, from welsh_dresser.kdl:
travel axis=-y body=assembly
pivot#
word-valued property; property in 2 of 116 examples (3 uses).
Shortest real use, from welsh_dresser.kdl:
travel kind=angle axis=z body=assembly pivot=Pin_Back