Standard parts (bt.parts)¶
Generators for the structures every cell has — fences, walls, tables,
pedestals, aluminium frame units cut from a maker's profile system
(frame_unit, FrameUnit), racks, conveyor bodies, pallets, light curtains, stairs, a
machining centre with its door and panel, a screw presenter with its
magazine, screws and compound solids, the shape library (appearance,
shaped_box) and the props drawn from it (trays, stages, cartons, bins, roll cages,
the racks a goods-to-person drive unit carries, stock on pallets, floor markings, a person, a gantry), and catalog objects set down
as they ship (prop — the scanned YCB objects) — built from ordinary residents
(boxes, frames, a device or a sensor) with their part
identity pinned, so the BOM counts them and the layout sheet labels them.
See Standard parts and CAD geometry.
bt.parts.fence(scene, "fence", path=[(-2, -2), (2, -2), (2, 2), (-2, 2)],
height=2.0, panel_pitch=1.0, door=(0, 2), model="ST20")
ped = bt.parts.pedestal(scene, "pedestal", height=0.5, position=(0, 0))
scene.set_robot_base_pose(*scene.frame(ped.frames[0]))
parts
¶
Standard structures, generated from parameters: fences, walls, tables, pedestals, racks, conveyor bodies, pallets, light curtains, stairs, control cabinets, a machining centre with its door, its panel and a vise — the scenery every cell has and nobody wants to model.
Each generator composes the ordinary scene API — add_box, add_frame,
add_conveyor, add_beam_sensor, set_part — so what it builds is plain
residents: boxes under a name prefix (fence/panels/n0, table/top), a
frame where the next thing mounts, a device or a sensor where one belongs,
and a part on the group with the quantity, so the BOM counts panels and
posts and the layout sheet labels the assembly once. Change a parameter and
the geometry, the BOM line and the sheet change together.
bt.parts.fence(scene, "fence", path=[(-2, -2), (2, -2), (2, 2), (-2, 2)],
height=2.0, panel_pitch=1.0, door=(1, 1), model="ST20")
ped = bt.parts.pedestal(scene, "pedestal", height=0.5, position=(0, 0))
scene.set_robot_base_pose(*scene.frame(ped.frames[0]))
Pass catalog= instead of a model string and the parameters come from the
catalog: the height is checked against the ones that are sold, the panels are
laid out in widths that exist, and every line of the BOM carries the part
number you would order it by.
bt.parts.fence(scene, "fence", path=[...], catalog="botrail/fence/mesh-guard",
height=2.0, door=(0, 1))
botrail does not model shapes. These are boxes arranged by parameters, and
that is the point: a fence is panels of a pitch along a path, a table is
a top on legs — the meaning is what the BOM and the sheet need, and the
few centimetres a real profile differs by change nothing a cell verifies.
Anything with a shape of its own comes in from CAD as a mesh (see the
Geometry Provider pattern in the standard-parts guide) and gets its
identity the same way, with set_part.
The forms a box cannot draw but every cell has — a carton with its lids
and tape, a pressed tray, a perforated basket, an adjuster foot — are a
small shape library shipped with botrail (SHAPES, unit-box USD layers
under botrail/_shapes/, authored in botrail-assets): appearance draws
an obstacle as one of them, scaled to its box, so the collision stays the
box the cell was taught against and the picture travels with the
resident; shaped_box places one as decoration. The props built on it —
tray, stage, carton, unit_load, marking, person, gantry — are
the generic things a cell is full of and nobody orders by part number,
generated from their dimensions like everything else here.
ALUMINIUM
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
BELT
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
BLACK_ANODIZED
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
BUTTON_BY_NAME
module-attribute
¶
BUTTON_BY_NAME = {
"cycle_start": "green",
"start": "green",
"feed_hold": "red",
"stop": "red",
"estop": "red",
"reset": "blue",
"clamp": "yellow",
"unclamp": "yellow",
"door": "white",
}
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
BUTTON_CAP
module-attribute
¶
Convert a string or number to a floating-point number, if possible.
BUTTON_COLORS
module-attribute
¶
BUTTON_COLORS = {
"green": (0.02, 0.35, 0.06),
"red": (0.55, 0.02, 0.02),
"yellow": (0.75, 0.55, 0.02),
"blue": (0.02, 0.1, 0.45),
"white": (0.8, 0.8, 0.78),
"black": (0.02, 0.02, 0.02),
}
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
BUTTON_FORCE_N
module-attribute
¶
Convert a string or number to a floating-point number, if possible.
BUTTON_TRAVEL
module-attribute
¶
Convert a string or number to a floating-point number, if possible.
CABINET
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
CAP_BLACK
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
CARDBOARD
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
CHECKER_PLATE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
CLEAR_SHEET
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
CONCRETE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
CONTROLLER_MOUNTS
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
DARK_STEEL
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
DETAIL_MODES
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
DOOR_DRIVES
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
DOOR_SPEED
module-attribute
¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
ESTOP_CAP
module-attribute
¶
Convert a string or number to a floating-point number, if possible.
ESTOP_FORCE_N
module-attribute
¶
Convert a string or number to a floating-point number, if possible.
FACES
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
FENCE_FRAME
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
FENCE_PANEL
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
FENCE_POST
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
FOAM
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
FRAME_TEMPLATES
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
HI_VIS
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
KLT_BLUE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
LABEL_PAPER
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
LATHE_APERTURE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
LATHE_CHAMBER
module-attribute
¶
Convert a string or number to a floating-point number, if possible.
LATHE_CHUCK
module-attribute
¶
Convert a string or number to a floating-point number, if possible.
LATHE_SIZE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
LATHE_SPINDLE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
LATHE_TURRET
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
LINE_GREEN
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
LINE_YELLOW
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
MACHINE_ACCENT
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
MACHINE_BED
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
MACHINE_SHELL
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
MACHINE_WINDOW
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
MOTOR
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
PACKING_TAPE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
PLASTER
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
POD_YELLOW
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
REFLECTOR
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
SAFETY_ORANGE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
SHAPES
module-attribute
¶
SHAPES = (
"adjuster",
"basket",
"bracket",
"carton",
"handle",
"highbay",
"hose",
"orikon",
"panel",
"person",
"person_pick",
"person_reach",
"pod",
"rim",
"roll_cage",
"tote",
"tray",
"tslot",
"tslot_2",
"waste_bin",
"workpiece",
)
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
STEEL
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
STRETCH_FILM
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
TABLE_STEEL
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
TRAY_STEEL
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
TYPE_CHECKING
module-attribute
¶
bool(x) -> bool
Returns True when the argument x is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.
VMC_APERTURE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
VMC_CHAMBER
module-attribute
¶
Convert a string or number to a floating-point number, if possible.
VMC_EXCHANGE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
VMC_FRONT_DOOR
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
VMC_HEAD_CLEARANCE
module-attribute
¶
Convert a string or number to a floating-point number, if possible.
VMC_SIZE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
VMC_TABLE
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
WOOD
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
ZINC
module-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
Box
¶
A box size = (x, y, z) centred at at, in the compound's frame.
at
class-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
Built
¶
What a generator put into the scene, by name — the obstacles, and the frames, devices and sensors that came with them — so the caller can mount on the frame, drive the device, or take the whole thing down.
remove
¶
Takes everything this generator added out of the scene (parts go with their residents).
Cylinder
¶
A cylinder of radius and length standing on at — the centre of
its bottom face — and rising along the compound's +Z.
at
class-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
FramePlan
¶
A template's cut list before anything is built: the members, the pairs
joined with a bracket, the member ends that take a cap, the members that
stand on a foot, the board on top (size, centre) if there is one, and an
enclosure's panels (tag, size, centre) and door leaf (size, centre, the
face it closes). Pure data — frame_unit_plan makes it, frame_unit
builds it, tests read it without a scene.
panels
class-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
lengths
¶
How many members there are of each length (metres, to 0.1 mm).
FrameUnit
¶
A frame built member by member from a system pack — for the shapes no
template has (an L-shaped bench, a camera post with an outrigger, a
cover with an opening). Place members in the unit's own frame (metres:
floor centre, x along the width, before yaw), say which pairs are
joined, where a cap or a foot goes, then build():
F = bt.parts.FrameUnit(scene, "rig", catalog="misumi/hfs/6-series", finish="black")
leg = F.member("leg", (0.0, 0.0, 0.0), (0.0, 0.0, 0.72))
beam = F.member("beam", (0.0, 0.0, 0.72), (1.14, 0.0, 0.72), section="3060")
F.joint(leg, beam) # one bracket, and the bolts and nuts it takes
F.cap(beam, "to")
built = F.build()
Every member is a box the robot can hit, cut to a length the pack sells
(matched against the profile's length_mm range and step — 1140.5 is a
length on a 0.5 mm grid, 1140.3 is refused with the nearest) and weighed
by the pack's kg/m. A rectangular profile (w x d) stands on edge when
horizontal and turns its d side along x when vertical, unless wide=
says which axis across the member the d side takes. With
detail="full" (the default with a catalog) the members are drawn as
the pack's own profile where it ships one (a visual authored at the
real cross-section, visual_scale: length) and as the shape library's
generic T-slot extrusion otherwise, tinted for clear or black anodising;
the brackets and caps are drawn as the pack's own articles where it
ships a visual for them (a bracket authored with its fold corner at
the origin, a cap as a plate with +z outward) and as the library's
bracket and a plain plate otherwise, the feet as the library's adjuster
— all out of collision — and counted; bolts and nuts sit inside the
slots and are not drawn at all, but they are still counted, on one
hidden resident each (<name>/hardware/bolts/lot), since a BOM line
needs something in the scene to stand for. The BOM is the cut list: the
unit on the group line, one line per profile length, one per hardware
article — a cap line per section where the pack sells them that way
(cap_3030, cap_3060 …). Changing detail changes none of it.
panel sets a sheet into a bay and door hangs a leaf over an
opening; they collide, and they are counted on lines of their own
(by size, without a part number) in either mode.
Without a catalog give section= (metres, a square side or (w, d)):
the members are one line (structure.frame, model= / manufacturer=)
and nothing is counted.
door
¶
The leaf that closes an opening: a box (local size and centre)
that collides, <name>/door, drawn like a panel of material, with
a frame of the same name at its centre and a BOM line of its own
(structure.door, model or one made from its size). It stands
closed; how it opens is the cell's — scene.add_linear_axis on
<name>/door makes it a sliding or a lifting door.
foot
¶
An adjuster foot under the lower end of a vertical member. The member should already stop a foot's height above the floor.
frame
¶
A named frame <name>/<tag> at a local point (the unit's yaw applies).
joint
¶
A bracketed butt joint between two members — one bracket
(rules.brackets_per_joint), with its bolts and nuts.
member
¶
member(
tag: str,
frm: tuple,
to: tuple,
*,
section: Optional[str] = None,
wide: Optional[int] = None,
) -> str
A profile from frm to to (local metres, along one axis), cut
from the pack's profile section (default: its first). For a
rectangular profile wide is the axis across the member its d
side runs along (default: x for a vertical member, z for a
horizontal one — on edge). Returns tag.
panel
¶
A sheet set into the slots of the members around a bay: a box
(local size and centre, its thinnest side the thickness) that
collides, drawn see-through for a clear material (PC, acrylic,
PET). Panels are counted by size — one BOM line per material
and width x height (<name>/panels/PC-1040x690) — and carry no
part number: the pack does not sell them.
plan
¶
plan(
plan: FramePlan,
*,
panel_material: str = "PC",
door_model: Optional[str] = None,
) -> FrameUnit
Everything a template planned, in one go — an enclosure's panels
and door in panel_material.
profile_role
¶
The pack's profile component for section — its role
(profile_3030), the role without the profile_ prefix (3030),
or, left out, the first profile the pack declares.
section
¶
A profile's cross-section (w, d), metres — from the pack's
dimensions_mm.w / .d (d defaults to w), or section=
without a catalog.
slab
¶
A board or a panel: a box (local size and centre) that collides.
With role, the pack's component of that role is its BOM line.
MachineTool
¶
Bases: botrail.parts.Built
What machine_tool built, plus the names a tending program
addresses: the side door's axis (door, None for a manual door or
none), what rides on that door (door_objects — the leaf and its
trim, for a robot that slides it by hand), its end-of-travel lanes
(door_lanes = closed, open — the axis's stop lanes, or two zone
sensors on a loose leaf), the stroke and the world direction it opens
along (door_travel, door_axis), the front door's closed switch and
the E-stop lane the machine's program is guarded by (front_door_lane,
estop), the operator panel's Built and the button sensors on it.
door_axis
class-attribute
¶
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
door_travel
class-attribute
¶
Convert a string or number to a floating-point number, if possible.
Member
¶
One profile of a frame unit: the pack's profile component it is cut
from (role) and its two end centres in the unit's own frame — metres,
floor centre, x along the width, before yaw. Members run along one
axis. wide is the axis across the member that the section's d side
runs along, which only matters for a rectangular profile: left out, a
vertical member turns it along x and a horizontal member stands on
edge (along z).
ScrewFeeder
¶
Bases: botrail.parts.Built
What screw_feeder built, plus what a fastening program addresses:
the device (an indexing source — start it for the next screw), the
present lane (a zone sensor over the pick point, on while a screw
stands there), the pick frame at the presented screw's tip (+Z up
the screw) and the screws in the order the feeder hands them out.
device
class-attribute
¶
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
pick
class-attribute
¶
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
present
class-attribute
¶
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
Workpiece
¶
Bases: botrail.parts.Built
What workpiece built: the housing and cover obstacles, the
dowels on the housing, the seat (the mating plane's centre, +Z out
of the housing — where the cover's underside lands) and the pack's
mounting data the joint is read from.
cover
class-attribute
¶
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
housing
class-attribute
¶
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
appearance
¶
appearance(
scene,
name: str,
shape: str,
size: tuple,
*,
offset: tuple = (0.0, 0.0, 0.0),
tint: bool = False,
) -> str
Draws the obstacle name as the library shape shape, scaled to
size — the box the shape fills, normally the obstacle's own — so the
picture moves, attaches, saves and exports with the resident while its
collision stays the box the cell was taught against. offset shifts
the picture inside that box (a basket floor sitting on an insert);
tint paints the whole shape the obstacle's colour instead of the
layer's finishes (a laminate panel in the bench's colour). The layer's
finishes replace any set_obstacle_material override. Returns name.
bin
¶
bin(
scene,
name: str,
size: Optional[tuple] = None,
position=(0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
wall: float | tuple[float, float] | None = None,
floor: Optional[float] = None,
yaw: float = 0.0,
detail: str | None = None,
color: tuple | None = None,
sleeve: str | None = None,
mass_kg: float | None = None,
model: str | None = None,
manufacturer: str | None = None,
**attributes,
) -> Built
A small-load container — a KLT, a tote, a folding container: size = (length, width,
height) outside, standing at position (the centre of its underside;
a bench top) turned by yaw. Four walls wall thick (one figure, or
(across the length, across the width)) stand under <name>/wall0..3
with the floor floor thick between them as <name>/floor, every one
a box the planner and the engine see — a thing set down inside lands
on the floor and stops at a wall — and the frame <name>/floor is the
floor's top centre, where a part sets down. Pinned as one part (bin)
on the group, so a physics bake keeps the five boxes one rigid unit
that rests, slides and is carried whole; mass_kg is what that unit
weighs. Full detail draws the library's sleeve round the boxes under
<name>/trim/, out of collision, in the bin's colour: sleeve names
it — "tote" (a KLT's ribs, stacking rim, grips and card pocket, the
default) or "orikon" (a folding container's walls with their hinge
bead, rib frame and hand holes) — or the pack does.
With catalog= — a bin spec pack such as botrail/bin/klt-vda4500 — a
container you can order: size (or length_mm / width_mm /
height_mm) is matched against the sizes sold and a combination nobody
sells is refused, the walls and floor are as thick as the pack's inside
dimensions say, and the BOM row carries the type number and the mass.
bolt
¶
bolt(
scene,
name: str,
*,
position: tuple,
thread: Optional[float] = None,
length: Optional[float] = None,
head_diameter: Optional[float] = None,
head_height: Optional[float] = None,
catalog: Optional[CatalogRef] = None,
quaternion=None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
standard: Optional[str] = None,
property_class: Optional[str] = None,
mass_kg: Optional[float] = None,
color: tuple = (0.62, 0.63, 0.66),
**attributes,
) -> str
One screw as one obstacle: a shank thread wide and length long
with its tip at the origin and +Z up the shank, and a cylindrical
head head_diameter × head_height on top of it — the envelope a
bit picks, a feeder presents and a hole receives. Pinned as a
fastener with its figures, so a magazine of the same screw lands on
the bill as one line with a count. bt.assembly.Fastener.place calls
this with a standard's figures.
With catalog= — the id of a fastener spec pack, or a package
directory — a screw you can order: the thread, pitch, head and drive
come from the pack, length (metres) and property_class are matched
against what it sells (its defaults when omitted), and the row carries
the article number and the mass the pack states.
buildable_lengths
¶
The edge lengths nearest length_mm that these panels can actually
make — what to move a corner to when a run does not come out.
cabinet
¶
cabinet(
scene,
name: str,
size: Optional[tuple] = None,
position: tuple | tuple = (0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
base: Optional[bool] = None,
plate: Optional[bool] = None,
base_height: Optional[float] = None,
yaw: float = 0.0,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.58, 0.56, 0.49),
**attributes,
) -> Built
A control cabinet: size = (width, depth, height) standing at
position (its centre, x, y[, floor z]), door face on -Y before yaw.
Adds the frame <name>/front at the centre of the door face at floor
level — where an operator stands, and what a maintenance-space check
will measure from — and pins the enclosure (structure.cabinet).
The panel builder's customisation is what this generator carries: the
enclosure is the article (what is inside it is other people's BOM
lines), and the plinth base and the mounting plate are articles of their
own. base= stands the body on its plinth (<name>/base), plate=
stands the mounting plate inside (<name>/plate) — each is one more
line on the BOM when a catalog names it.
With catalog= — the id of a cabinet spec pack, or a package directory —
an enclosure you can order: width, depth and height are matched against
the sizes that are sold, the BOM row carries the article number they
compose into, and base and plate default to whatever the pack sells
(pass base=False / plate=False to leave them out). A combination
nobody sells is refused by the pack's mass table.
detail="full" (the default with a catalog) draws the door leaves and
their handles — or the pack's own drawing (trim:) — as decoration that
never collides. The massing stays the body (and its plinth).
carton
¶
carton(
scene,
name: str,
size: tuple,
position,
*,
yaw: float = 0.0,
color: tuple = (0.62, 0.45, 0.26),
mass_kg: float | None = None,
model: str | None = None,
manufacturer: str | None = None,
detail: str | None = None,
**attributes,
) -> str
A shipping carton size = (length, width, height) standing at
position — the centre of its bottom face — turned by yaw: one
obstacle, so it attaches, tracks and saves as one thing, drawn in full
detail as the library's folded, taped and labelled box. Pins one part
(workpiece), its model the RSC size in millimetres unless given, with
mass_kg when known — what a payload check reads. Stock that is only
scenery: scene.remove_part(name) after. Returns the name.
charging_station
¶
charging_station(
scene,
name: str,
position: tuple | tuple = (0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
yaw: float = 0.0,
length: Optional[float] = None,
width: Optional[float] = None,
height: Optional[float] = None,
plate: Optional[float] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.42, 0.44, 0.47),
**attributes,
) -> Built
A vehicle charging station: the housing, and the charging plate on the
floor in front of it that the vehicle backs onto. position is the
housing's centre on the floor; the plate extends along local +X (rotated
by yaw), which is the side the vehicle arrives from. Adds the frame
<name>/dock on the floor at the plate's outer edge with +X pointing
away from the housing — the vehicle's charging face stands here, so a
vehicle whose contacts are at the back parks with its body centred half a
body length along that +X. Pins the charger (vehicle.charger).
With catalog= — the id of a charger spec pack, or a package directory —
the housing and plate come from the pack (omit the sizes) and the supply
the site provides (supply_vac=) is checked against what it takes.
chuck
¶
chuck(
scene,
name: str,
position: tuple,
quaternion: Optional[
tuple[float, float, float, float]
] = None,
*,
diameter: float = 0.165,
length: float = 0.085,
jaws: int = 3,
jaw_height: float = 0.03,
jaw_width: float = 0.025,
opening: float = 0.05,
max_opening: Optional[float] = None,
catalog: Optional[CatalogRef] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.2, 0.21, 0.23),
**attributes,
) -> Built
A lathe chuck: a diameter body length long with its face at
position, its axis the +Z of quaternion (pass a lathe's
<name>/spindle frame — bt.parts.chuck(scene, "chuck",
*scene.frame("lathe/spindle"))), and jaws jaw blocks standing
jaw_height off the face around a part of opening diameter — the
gripping diameter, so a robot loading a part along the axis meets
the jaws where they are. Frame <name>/face: the face centre, +Z out
along the spindle axis (a load comes in along -Z). Part: fixture.chuck
with the diameter, the opening and the jaw count; with catalog= the
diameter is matched against the ones sold and the maximum opening
comes from the pack.
compound
¶
compound(
scene,
name: str,
solids: Sequence[Union],
position: tuple,
*,
quaternion=None,
color: tuple = (0.42, 0.44, 0.47),
finish: Optional[tuple] = None,
segments: int = 32,
) -> str
One obstacle made of several primitives — a plate with a boss, a
screw's shank and head — where add_box and add_cylinder would make
one obstacle each and a thing the cell hands around (attaches, feeds,
tracks) has to be one resident.
The solids (Box, Cylinder) are written as a mesh into botrail's
cache (~/.cache/botrail/parts, or BOTRAIL_CACHE_DIR), keyed by
their figures so the same shape is one file, and loaded with
add_mesh at position / quaternion — collision is the mesh's
convex decomposition, like any mesh. Returns the obstacle's name.
controller
¶
controller(
scene,
name: str,
robots: Sequence[str],
position: tuple | tuple = (0.0, 0.0),
*,
size: Optional[tuple] = None,
catalog: Optional[CatalogRef] = None,
variant: Optional[str] = None,
detail: Optional[str] = None,
yaw: float = 0.0,
mount: str = "floor",
channels: Optional[list] = None,
programs: Optional[list] = None,
uplink=None,
cable_m: Optional[float] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.58, 0.56, 0.49),
**attributes,
) -> Built
A robot controller box — the cabinet an arm cannot run without — as
the three things it is at once: the box <name>/body (size = (width,
depth, height), standing on position — its footprint centre, x, y[,
the level it sits at] — door face on -Y before yaw), the
robot_controller I/O node <name> driving robots (its place is
the box; channels=, programs=, uplink= as add_io_node takes
them), and one BOM line (robot_controller) carrying mount, the
robot cable length cable_m and whatever identity is given. The frame
<name>/front sits at the centre of the door face at the box's level
— where somebody stands to service it. Declaring the node here takes
the arm's derived controller line off the bill: the box, the node and
the line are one thing.
A cell that wired the node first (add_io_node(name, ...) with its
channels and bindings) keeps that wiring: the box adopts the node,
which must drive the same robots; channels= / programs= /
uplink= given here override what it had.
With catalog= — the id of a controller spec pack, or a package
directory — a cabinet you can order: variant= picks the enclosure
the maker sells it in (A-cabinet, Mate, ...), the box takes that
variant's size (rules.size_mm_by_variant, else the body's fixed
dimensions, else the pack's footprint and height), the line its part
number and mass, cable_m defaults to the standard robot cable
(electrical.cable.standard_m; an option length must be one the pack
lists), channels to the pack's own I/O table (electrical.io),
mount is checked against rules.mount, and the service clearance
the maker asks for in front (rules.clearance_mm.front) rides on the
line as service_clearance_mm.
detail="full" (the default with a catalog) draws the door and its
handle — or the pack's own drawing (trim:) — as decoration that never
collides; the massing stays the body.
conveyor
¶
conveyor(
scene,
name: str,
length: Optional[float] = None,
width: Optional[float] = None,
position: tuple | tuple = (0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
direction: tuple = (1.0, 0.0),
speed: Optional[float] = None,
running: bool = False,
zone_height: float = 0.15,
belt_thickness: Optional[float] = None,
rail: Optional[float] = None,
legs: bool = True,
leg: Optional[float] = None,
stand_span: Optional[float] = None,
rollers: Optional[tuple[float, float]] = None,
roller_color: Optional[tuple] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.2, 0.21, 0.23),
**attributes,
) -> Built
A belt conveyor: length along direction, width across, its belt
surface centred at position (x, y, z of the surface). Builds the body —
belt slab, two side rails, legs — as obstacles under <name>/, and the
conveyor device <name> whose transport zone sits on the belt
(zone_height tall, speed along direction). The part is pinned on the
device (conveyor): the body is its geometry, not a second product. Adds
the frames <name>/infeed and <name>/outfeed at the belt ends.
rollers=(pitch, diameter) makes it a roller conveyor: the same slab
collides, but full detail draws the rollers across the frame — tops at
the conveying height, roller_color (zinc by default) — as one mesh out
of collision, and the part is a conveyor.roller. stand_span spaces
the stands at most that far apart (a pair at each end without it).
With catalog= — the id of a conveyor spec pack, or a package directory —
a conveyor you can order: the length, belt width and stand height are
matched against the ones that are sold (omit them and the catalog's
defaults apply, so position may be given as (x, y)), the speed is
checked against the range the drive covers, and the mass follows the
length. The stands are spaced by the catalog's maximum span and land on
the BOM as their own line.
duct
¶
duct(
scene,
name: str,
path,
*,
size: Optional[tuple[float, float]] = None,
z: float = 0.0,
wall: float = 0.0015,
catalog: Optional[CatalogRef] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.42, 0.44, 0.47),
**attributes,
) -> Built
A floor duct or cable tray along path — floor points (x, y) (or
(x, y, z)) of its centerline, in order — as a box per straight run
under <name>/run{i} (runs overlap by half a width at the corners),
size = (width, height) of the outer section, standing on z. The
routing support <name> (bt.routing) has its centerline at mid
height inside the duct and the inner section less the wall; a route
passes it with via=[name] (or bt.routing.through(name)). The part
(cable.duct) carries the run length and the section.
Nothing is sized here: the duct is as wide as you say (100 x 60 mm when
you say nothing), and a bundle that will not fit is the routing
report's duct_fill to tell. With catalog= — a cable.duct spec pack,
or a package directory — the inner section the pack states sets the
size (plus the wall), and its maker and part number the part.
fence
¶
fence(
scene,
name: str,
path: Sequence[tuple],
*,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
height: Optional[float] = None,
panel_pitch: Optional[float] = None,
post: Optional[float] = None,
panel_thickness: Optional[float] = None,
closed: bool = True,
door: Optional[tuple[int, int]] = None,
door_model: Optional[str] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
post_model: Optional[str] = None,
panel_color: tuple = (0.55, 0.58, 0.6),
post_color: tuple = (0.16, 0.17, 0.19),
**attributes,
) -> Built
A safety fence along path (floor corners, metres), with a post at
every corner and between panels. closed joins the last corner back to
the first. door=(edge, slot) makes that slot the door — its own
obstacle <name>/door and its own BOM line.
Without a catalog each edge is split into panels of about panel_pitch
(the pitch is stretched so an edge takes a whole number), and two parts
are pinned: <name> (the panels, qty = panels, with the model /
manufacturer / mass_kg you passed) and <name>/posts.
With catalog= — the id of a fence spec pack, or a package directory —
the fence is built out of panels that exist. height is checked against
the heights that are sold, the widths come from the catalog and each edge
is filled with the fewest of them that reach its length, and any catalog
parameter can be set by name (mesh_mm="20x20"). The parts pinned are
then <name> (the fence as one product, so the layout sheet still labels
it once), one group per panel width carrying that width's part number
and count, <name>/posts and <name>/door — a bill you can order from.
detail="full" (the default with a catalog) draws each panel the way it
looks — a tube frame with a grid of wire in it, posts of the section the
catalog sells, a plate under each — as decoration that never collides;
the panel slab underneath still does, so nothing about the verification
changes. detail="plain" is the bare massing. Returns the names it
made.
frame_unit
¶
frame_unit(
scene,
name: str,
size: Optional[tuple] = None,
position: tuple | tuple = (0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
template: str = "table",
detail: Optional[str] = None,
section: Optional[Union[str, float, tuple]] = None,
legs: Optional[str] = None,
rails: Optional[str] = None,
lower_rails: Optional[float] = 0.0,
feet: Optional[bool] = None,
top: Optional[float] = None,
panels: Optional[Sequence[str]] = None,
openings: Optional[dict] = None,
door: Optional[str] = None,
panel: float = 0.005,
panel_material: str = "PC",
door_model: Optional[str] = None,
yaw: float = 0.0,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: Optional[tuple] = None,
**attributes,
) -> Built
An aluminium-frame unit from a template — table: four legs under a
ring of rails, size = (width, depth, height) the frame's envelope,
standing on the floor at position (its centre, x, y[, floor z]),
turned by yaw. Adds the frame <name>/top at the centre of the top
face (the board's, if top gives one a thickness) and pins the unit
(structure.frame) on the group.
enclosure: a machine guard — the same box of twelve members, its
lower ring flush with the bottom so it stands on a base (position
with the base's top as its z; no feet unless asked), clad with
panel-thick sheets of panel_material in the slots of the members
on the faces panels names (default all five: front -y, back,
left, right, top). openings={face: ((lo, hi), (lo, hi))} cuts
one opening in a face — the unit's own coordinates along the face's
two axes (x, z for front and back; y, z for the sides; x, y for the
top), None for a side that runs to the edge — framed by mid-posts and
mid-rails that join the cut list; door=face hangs a leaf over that
face's opening, <name>/door, standing closed just proud of the face
(drive it with scene.add_linear_axis). Panels are BOM lines by size
and the door one line, without part numbers (door_model names it).
With catalog= — the id of a frame system pack (a maker's profile
series: profiles by the millimetre, brackets, bolts, nuts, caps, feet),
or a package directory — the members are cut to lengths the pack sells,
from the profile section chosen ("3030"; default the pack's first;
legs= / rails= give the legs and the rails a profile of their own —
a rectangular rail stands on edge, a rectangular leg turns its wide side
along the width), and the BOM is the cut list: one line per profile
length (HFS6-3030-1140 x2 …), one per hardware article, counted from
the joints the way the makers' own standard units are (see
frame_unit_plan). lower_rails is
the lower ring's height above the legs' bottom (None for none); feet
puts the pack's adjusters under the legs (default: when the pack sells
them); a pack that sizes width_mm / depth_mm / height_mm may
leave size out. Without a catalog section is the profile's side in
metres (or (w, d)) and the unit is one line.
detail="full" (the default with a catalog) draws the members as T-slot
extrusions (the pack's own profile, or the shape library's tslot,
tinted for the finish) and adds the brackets, caps and feet — decoration
that never collides. The members are what a robot can hit in either
mode, and the BOM is the same in either mode.
frame_unit_plan
¶
frame_unit_plan(
template: str,
size: tuple,
section: Union[float, tuple],
*,
lower_rails: Optional[float] = 0.0,
foot: float = 0.0,
top: float = 0.0,
role: str = "profile",
legs: Optional[Union[float, tuple]] = None,
rails: Optional[Union[float, tuple]] = None,
legs_role: Optional[str] = None,
rails_role: Optional[str] = None,
panels: Optional[Sequence[str]] = None,
openings: Optional[dict] = None,
door: Optional[str] = None,
panel: float = 0.005,
) -> FramePlan
The members a template is cut into — arithmetic only, no scene.
table: four legs under a ring of rails, size = (width, depth, height)
the frame's envelope (the height is to the top of the ring, a board
goes above it), section the profile's cross-section — a square side,
or (w, d) for a rectangular one; legs / rails give the legs and
the rails a section of their own (and legs_role / rails_role the
pack component each is cut from). The rule is the one the makers'
standard units follow (MISUMI's HAU-BA set contents): the two width
rails on top run the full width and sit on the legs; every other
rail is butt-jointed between them (a depth rail between the width
rails, a lower rail between the legs); the legs are a rail's height
shorter than the frame, less the foot under them. A rectangular rail
stands on edge (its d side vertical) and a rectangular leg turns its
d side along the width. lower_rails is the height of the lower
ring's underside above the legs' bottom (0 = flush with the floor, the
standard unit; None = no lower ring). Every 3-member corner is three
bracketed joints, the four exposed ends of the top width rails get a
cap, each leg a foot when foot > 0, and top > 0 puts a board that
thick on the ring.
For W 620 x D 480 x H 570 on a 30 mm section this is 620 x2, 560 x2,
420 x4, 540 x4 — MISUMI's published set for HAUBA6-3030-W620-D480-H570.
enclosure: the same box of twelve members — the lower ring flush with
the bottom, standing on whatever is under it — clad with panel-thick
sheets set into the slots of the members around each bay (6 mm into
each slot, the sheet on the members' centre line) on the faces
panels names (front -y, back +y, left -x, right +x, top;
default all five). openings maps a face to the one opening it has,
((lo, hi), (lo, hi)) along the face's two axes in the unit's frame
(x then z for front / back, y then z for left / right, x then y for the
top; None runs that side to the face's edge): a mid-post or mid-rail
frames each side that stops short of the edge, butt-jointed between the
members around it, and the bays left beside, below and above the
opening take panels. door names a side face whose opening gets a
leaf: a sheet lapping half a member over every edge, standing just
proud of the face so it can slide over the panels beside it.
gantry
¶
gantry(
scene,
name: str,
span: float,
height: float,
position,
*,
yaw: float = 0.0,
section: float = 0.05,
overhang: float = 0.03,
color: tuple = (0.2, 0.21, 0.23),
model: str | None = None,
manufacturer: str | None = None,
**attributes,
) -> Built
A portal over a station — the beam a camera or a light hangs from:
two square posts section wide, span apart along the local X (turned
by yaw) either side of position (the floor point between them),
height tall, and the beam across their tops overhanging each post by
overhang — <name>/post_l, <name>/post_r, <name>/beam, all in
collision. The frame <name>/beam is the beam's centre underside, the
mount. Pins one part (structure.gantry) on the group.
lathe
¶
lathe(scene, name: str, size: Optional[tuple] = None, position: tuple | tuple = (0.0, 0.0), *, yaw: float = 0.0, aperture: Optional[tuple] = None, door: Union[str, None, object] = <object object at 0x7f7eafce55a0>, door_travel: Optional[float] = None, door_speed: Optional[float] = None, spindle: Optional[tuple] = None, chamber: Optional[float] = None, turret: Optional[tuple] = None, tailstock: bool = False, panel: Optional[str] = 'front', buttons: Optional[Sequence[str]] = None, panel_pitch: float = 0.045, wall: float = 0.06, catalog: Optional[CatalogRef] = None, detail: Optional[str] = None, model: Optional[str] = None, manufacturer: Optional[str] = None, color: tuple = (0.62, 0.63, 0.62), **attributes) -> MachineTool
A CNC lathe as the envelopes a tending cell verifies against —
the turning counterpart of machine_tool. size = (length, depth,
height) stands at position, front face on -Y before yaw, the
spindle axis along the length (+X toward the tailstock). Without
arguments it is the Haas ST-10 of the public spec pages (LATHE_*
above); the front opening, the spindle's height and depth are design
values, the first to replace when the drawing is at hand.
What it puts in the scene, all of it collision-checked:
- the enclosure — bed, the rear block behind the
chamber, roof, end walls, and the front wall around the door openingaperture = (width, height, sill), centred on the spindle; - the headstock and the spindle nose at
spindle = (x from the body centre, depth behind the front wall's inner face, height), the turret envelopeturret = (x, y, z size)right of it at spindle height, and a tailstock block at the far end whentailstock=True— the chuck is a part of its own (bt.parts.chuck(scene, "chuck", *scene.frame("<name>/spindle"))); - the front door: a leaf that slides toward the tailstock end by
door_travel.door="servo"/"air"make it a linear axis<name>/front_doorwith the stopsclosedandopen, checked against every robot each tick;door="manual"(the default) leaves the leaf loose for a robot that takes the handle;door=Nonebuilds a solid front. Either way the lanes<name>/front_door/closedand/openread the leaf at its ends of travel; - an operator panel on the front face, right of the opening
(
panel="front";Noneleaves it off).
Frames: <name>/spindle (the spindle nose centre, +Z out along the
axis toward the tailstock — a load comes in along -Z),
<name>/entry (the opening's centre, 150 mm outside the leaf),
<name>/door/front/handle (+Z into the leaf), the panel's.
The returned MachineTool names the door axis, its lanes, the stroke
and its world direction, the panel and its buttons, the E-stop lane —
what bt.tending and a teach read. A lathe has the one door, so its
front_door_lane is None and no door-exclusivity guard applies.
Refused rather than clipped: an opening that does not fit the front,
a stroke that runs the leaf off the body, a spindle outside the
chamber.
With catalog= a lathe spec pack's mechanical.envelope
(doors.front, spindle, turret, chamber_depth_mm) and the door
drive it sells (front_door) stand in for the figures, its articles
land on the bill, and its interface rides on the result.
light_curtain
¶
light_curtain(
scene,
name: str,
frm: tuple,
to: tuple,
*,
height: Optional[float] = None,
beam_height: Optional[float] = None,
column: float = 0.04,
watch_robot: bool = True,
watch: Optional[list[str]] = None,
catalog: Optional[CatalogRef] = None,
resolution: Optional[float] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.16, 0.17, 0.19),
**attributes,
) -> Built
A light curtain between two floor points: two mounting columns
<name>/column_a|b of height (1.2 m unless given), and a beam sensor
<name> at beam_height (half the height by default) spanning the
gap between their lens faces — pulled in off the column centres, so the
curtain is not born tripped by its own housings. With the defaults it
trips on anything that enters the field, robot links and objects alike;
watch=[...] with watch_robot=False narrows it to the named objects,
watch=[] to robot links alone. The part (sensor.light_curtain) is
pinned on the sensor; the columns are its mounting geometry.
With catalog= — the id of a light-curtain spec pack, or a package
directory — a curtain you can order: height is the protective height
and is matched against the ones sold, resolution (mm — the smallest
object it must catch: 14 for a finger, 25 for a hand) picks the type,
the columns take the maker's section, and the BOM row carries the model
number of the emitter/receiver pair and its mass. A beam longer than the
curtain's operating range is refused with the numbers — the same
range_mm a requirement check would ask of it.
machine_tool
¶
machine_tool(scene, name: str, size: Optional[tuple] = None, position: tuple | tuple = (0.0, 0.0), *, yaw: float = 0.0, aperture: Optional[tuple] = None, door: Union[str, None, object] = <object object at 0x7f7eafce55a0>, door_side: Union[str, object] = <object object at 0x7f7eafce55a0>, door_travel: Optional[float] = None, door_speed: Optional[float] = None, front_door: Union[tuple, None, object] = <object object at 0x7f7eafce55a0>, chamber: Optional[float] = None, table: Optional[tuple] = None, exchange: Optional[tuple] = None, head_clearance: Optional[float] = None, panel: Optional[str] = 'front', buttons: Optional[Sequence[str]] = None, panel_pitch: float = 0.045, wall: float = 0.06, catalog: Optional[CatalogRef] = None, detail: Optional[str] = None, model: Optional[str] = None, manufacturer: Optional[str] = None, color: tuple = (0.62, 0.63, 0.62), **attributes) -> MachineTool
A vertical machining centre as the envelopes a tending cell
verifies against — not its shape. size = (width, depth, height)
stands at position (its centre, x, y[, floor z]), front face on -Y
before yaw. Without arguments it is the FANUC ROBODRILL
α-D21MiB5 Plus of the public catalogue (VMC_* above): change any
figure and the envelopes, the frames and the BOM line change together.
What it puts in the scene, all of it collision-checked:
- the enclosure — bed, side walls, roof, the rear column block (the
last
depth - chamberof the body), and a front wall around the front door opening (front_door = (width, height, sill)), with its leaf standing closed; - the table
table = (width, depth, top height)at the exchange position (exchange = (x, y)offset from the chamber centre, x toward the door side — a table that traverses to the door is what a tending robot reaches), and the spindle head above it fromhead_clearance(nose to table at Z max) to the roof; - the side door: an opening
aperture = (width, height, sill)in thedoor_sidewall and a leaf that slides toward the rear bydoor_travel.door="servo"/"air"make it a linear axis<name>/side_doorwith the stopsclosedandopen(bt.seq.move_to(door, "open")opens it,move_to(door, "closed")closes; the speed comes from the drive —door_speedoverrides), and the rollout checks the leaf against every robot each tick: a door closing on an arm is aDeviceCollisionby name.door="manual"leaves the leaf loose, for a robot that takes the handle (bt.seq.attachthedoor_objectsand run acartesian_line);door=Nonebuilds a plain wall. Either way the lanes<name>/side_door/closedand/openread the leaf at its ends of travel — the axis's stop lanes, or two zone sensors on a loose leaf — the limit switches a door interlock is written from; - an operator panel (
operator_panel) withbuttonsatpanel_pitch, on the front face (panel="front") or on the door-side wall ahead of the opening (panel="door", where a robot at the door reaches it);panel=Noneleaves it off.
Frames: <name>/table (centre of the table top), <name>/entry (the
side opening's centre, 150 mm outside the door leaf — where a robot
waits), <name>/door/side/handle (the leaf's handle, +Z into the
leaf), and the panel's <name>/panel/<button>[/press].
Refused rather than clipped, like a wall plan that does not close: an opening that does not fit its wall, a leaf whose stroke runs off the body, a spindle head that would stand through the roof.
detail="full" adds framed transparent windows, the enclosure skirt,
the accent band and the stack light.
These are authored visual details, not measured manufacturer CAD.
Door leaves keep their solid collision envelopes behind the drawn
panels and glazing. The part is pinned on the
group (machine_tool.vmc), the side door as <name>/side_door
(machine_tool.door, with its drive and stroke), the panel and its
buttons by operator_panel.
With catalog= — the id of a machine-tool spec pack, or a package
directory — a machine you can order: the body, the openings, the
table and the head come from the pack's mechanical.envelope, the
options it sells (column_mm, side_door, door_side) are chosen
by name and refused when nobody sells them, the door's speed follows
the drive's published time, every article lands on the bill with its
number, and the pack's interface (its handshake template and
signal table) rides on the returned MachineTool for bt.tending.
marking
¶
marking(
scene,
name: str,
*,
rect: tuple[float, float, float, float] | None = None,
line: tuple[tuple, tuple] | None = None,
dash: tuple[float, float] | None = None,
width: float = 0.08,
color: tuple = (0.85, 0.62, 0.05),
floor: float = 0.0,
thickness: float = 0.003,
) -> Built
Paint on the floor. rect = (x0, y0, x1, y1) outlines an area with
four strips <name>/0 … <name>/3; line = ((ax, ay), (bx, by)) is
one stripe <name>, or the dashes <name>/0 … with dash = (on, off).
Each is width wide and thickness thick, lying on floor (a slab's
top). Out of collision and under the layout sheet's ground_z, so the
drawing shows them on its ground layer and nothing else notices them.
mobile_rack
¶
mobile_rack(
scene,
name: str,
size: tuple,
position=(0.0, 0.0),
*,
clearance: float = 0.4,
style: str = "bins",
lift: float = 0.0,
yaw: float = 0.0,
collide: bool = True,
detail: str | None = None,
color: tuple | None = None,
model: str | None = None,
manufacturer: str | None = None,
**attributes,
) -> Built
A rack a drive unit carries — the shelf of a goods-to-person (GTP)
system: size = (width, depth, height) on four corner uprights, standing
at position (the floor point under its centre) turned by yaw, its
underside clearance above the floor — the room a drive unit drives into
to lift it. lift raises the whole rack that far: one a drive unit
carries, its feet off the floor.
style="bins" is the inventory pod: the storage from the base frame to
the top collides as one block (<name>/storage) and is drawn as the
library's fabric bins on all four faces. style="open" is a case rack:
a deck with a tray on it (<name>/deck), a rail round the top of three
sides (<name>/rail_*) and the face at +x open — what stands on the deck
comes out that way; the frame <name>/deck is the tray's top centre,
where a load sits. The uprights (<name>/upright0..3) collide in both,
floor to top.
Full detail draws the base frame and the top frame (or the deck's frame,
plate and tray, and a mid rail), out of collision under <name>/trim/; collide=False takes the whole rack
out of collision (a field of pods nothing drives past). Pins one part
(structure.rack) on the group.
operator_panel
¶
operator_panel(
scene,
name: str,
position: tuple,
*,
yaw: float = 0.0,
tilt: float = 0.0,
size: tuple = (0.3, 0.22),
thickness: float = 0.03,
buttons: Sequence[str] = (
"cycle_start",
"feed_hold",
"reset",
"estop",
),
columns: Optional[int] = None,
pitch: float = 0.045,
cap: float = 0.0285,
travel: float = 0.0026,
proud: float = 0.01,
watch_robots: Optional[list[str]] = None,
catalog: Optional[CatalogRef] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
button_model: Union[
str, Mapping[str, str], None
] = None,
color: tuple = (0.2, 0.21, 0.23),
detail: Optional[str] = None,
**attributes,
) -> Built
An operator panel: a plate size = (width, height) centred at
position, its face toward -Y before yaw, tilted up toward the
operator by tilt, with a grid of 22 mm pushbuttons on it.
A button is three things. A cap (decoration — drawn, never collided),
a zone sensor <name>/<button> the size of the cap and as deep as
the button's operating travel, sitting inside the cap face — so a
tool that touches the cap reads nothing and one that pushes it in the
2.6 mm a 22 mm actuator travels turns the input on, for as long as it
is held — and two frames: <name>/<button> on the cap face and
<name>/<button>/press the travel below it, both with +Z pointing
into the panel, which is where a pressing tool aims its approach axis.
Nothing moves: the stroke is a depth, and the input is the meaning.
A neighbouring button's zone is the check that a wide tool did not
press two.
Cap colours follow the name (cycle_start green, feed_hold red,
reset blue, …) and estop is drawn as the ø40 mushroom head with
its collar; each button's sensor is pinned as an hmi.button with the
head size, travel and actuating force, the panel itself as an
hmi.panel. By default any robot link trips a button;
watch_robots=[...] narrows it to the arms named.
With catalog= — the id of a pushbutton-box spec pack, or a package
directory — a box you can order: the number of buttons is matched
against the sizes sold (the box's face follows), the pitch, the cap
and the travel come from the pack, and the box, its buttons and the
E-stop land on the bill with their article numbers. An operator the
pack sells no article for comes with the box (a complete station) and
is listed as included, not bought again; a pack's box trim draws the
enclosure in place of the plate.
pallet
¶
pallet(
scene,
name: str,
position: tuple | tuple,
*,
size: tuple = (1.2, 1.0, 0.144),
deck_boards: int = 5,
yaw: float = 0.0,
model: Optional[str] = "EPAL 1",
manufacturer: Optional[str] = None,
color: tuple = (0.52, 0.36, 0.18),
**attributes,
) -> Built
A wooden pallet size = (length, width, height) on the floor at
position (centre), laid out like an EPAL 1: three bottom boards along
the length, nine blocks, three stringers and deck_boards deck boards,
so a fork — or a pallet truck's arms — enters from the short side
between the bottom boards. Adds the frame <name>/top at the centre
of the deck and pins one part (pallet).
pallet_rack
¶
pallet_rack(
scene,
name: str,
position: tuple | tuple = (0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
yaw: float = 0.0,
bays: int = 1,
width: Optional[float] = None,
depth: Optional[float] = None,
height: Optional[float] = None,
levels: Optional[int] = None,
beam_heights: Optional[Sequence[float]] = None,
upright: Optional[float] = None,
upright_depth: Optional[float] = None,
beam: Optional[float] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.42, 0.44, 0.47),
**attributes,
) -> Built
Pallet racking: bays bays of clear width in a row along local +X
(rotated by yaw), depth deep, height tall, with levels beam
levels — the floor is level 0 and is not counted. position is the
centre of the run on the floor; the aisle faces are ±Y. An upright frame
(two posts, upright by upright_depth) stands between every bay and at
both ends, and each level is a pair of beam-tall beams the pallets rest
on, their tops at beam_heights (evenly spaced by default, the top one
100 mm under the upright top).
Adds the frame <name>/bay{i}/level{j} at the centre of every pallet
seat — j = 0 on the floor, then each beam top upward — which is where a
pallet is put and what a pick targets. Pins the racking: without a
catalog one structure.rack line for the run; with catalog= — the id
of a pallet rack spec pack, or a package directory — the dimensions and
beam count are matched against what is sold, beam tops snap to the
maker's adjustment pitch, and the run is bought as one 単体 unit plus
(bays − 1) 連結 extensions, each on the BOM under its own part number.
pallet_stand
¶
pallet_stand(
scene,
name: str,
position: tuple | tuple = (0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
yaw: float = 0.0,
length: Optional[float] = None,
width: Optional[float] = None,
inner: Optional[float] = None,
support: Optional[float] = None,
height: Optional[float] = None,
leg: Optional[float] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.2, 0.21, 0.23),
**attributes,
) -> Built
A pallet stand: the floor-standing rack a pallet-lift AMR drives under
to pick a pallet up or set it down. Two sections stand either side of the
vehicle's path, each two posts under a support rail with a stop at the
far end; the pallet rests across both rails, support over the floor.
position is the stand's centre on the floor; the open end faces local
+X (rotated by yaw), so a vehicle drives in along -X and backs out the
way it came. length runs along the path, width is the outside of the
two sections, inner the gap between them the vehicle passes through.
Adds the frame <name>/pallet at the centre of the pallet seat (+Z up)
and <name>/entry on the floor at the open end with +X pointing into the
stand — the vehicle's heading when it docks. Pins the stand
(structure.pallet_stand).
With catalog= — the id of a pallet stand spec pack, or a package
directory — every dimension comes from the pack (omit them all), the
pallet it takes is recorded, and the stand lands on the BOM under the
article the maker sells it as.
pedestal
¶
pedestal(
scene,
name: str,
height: Optional[float] = None,
position: tuple | tuple = (0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
top: Optional[tuple] = None,
base: Optional[tuple] = None,
column: Optional[float] = None,
plate: Optional[float] = None,
yaw: float = 0.0,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.2, 0.21, 0.23),
**attributes,
) -> Built
A robot pedestal: base plate, column, top plate, height from floor
to the top face at position. Adds the frame <name>/mount at the top
centre — the robot's base pose (scene.set_robot_base_pose(*scene.frame(
"<name>/mount"))) — and pins one part (structure.pedestal).
With catalog= — the id of a pedestal spec pack, or a package directory —
a stand you can order: the height is matched against the ones that are
sold (omit it for the pack's default) and the column, plates and their
footprints come from the pack, so the BOM names the stand a robot is
actually bolted to.
detail="full" (the default with a catalog) adds the gussets between the
column and the base — decoration that never collides.
person
¶
person(
scene,
name: str,
position,
*,
height: float = 1.7,
footprint: tuple = (0.4, 0.4),
yaw: float = 0.0,
color: tuple = (0.85, 0.75, 0.3),
pose: str = "stand",
detail: str | None = None,
) -> str
A person, as the safety scenarios need one: a box footprint by
height standing at position (the floor point between the feet),
facing yaw, in collision — a walk into it is refused, a light curtain
or a zone reads it, a scenario moves it into the gate. Full detail draws
the library's figure in it, scaled to height by its own proportions:
pose "stand" (at ease), "reach" (handling something before the hips
with both hands) or "pick" (reaching into a bin at chest height half a
metre ahead — the arm out of the box, which stays the body). color is
the box's, for what draws no figure (a colour picture, a USD without
materials). Nothing is pinned. Returns the name.
photoelectric
¶
photoelectric(
scene,
name: str,
frm: tuple,
to: tuple,
*,
body: Optional[tuple] = None,
watch_robot: bool = False,
watch: Optional[list[str]] = None,
catalog: Optional[CatalogRef] = None,
sensing: Optional[str] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.2, 0.21, 0.23),
**attributes,
) -> Built
A photoelectric sensor: a beam <name> from the lens at frm to
to (both in metres, 3D) that trips on the named objects (watch — a
workpiece arriving on the belt) and/or on any robot link
(watch_robot), and the sensor body <name>/body behind the lens —
body = (depth, width, height), the amplifier-in-head block sold by
the million (20 x 11 x 31 mm unless given). The part
(sensor.photoelectric) is pinned on the sensor.
What stands at to follows the sensing method: a through-beam pair
puts the receiver <name>/receiver there, a retroreflective sensor its
reflector <name>/reflector, a diffuse one nothing — the beam ends on
the target itself.
With catalog= — the id of a photoelectric spec pack, or a package
directory — a sensor you can order: sensing picks the method the pack
sells (through_beam / retroreflective / diffuse / ...), the other
axes (sensing_range_mm, output, ...) are chosen by name, the body
takes the maker's dimensions, the BOM row carries the model number and
mass, and a reflector the maker sells separately is a line of its own.
A beam longer than the sensing range is refused with the numbers — the
same sensing_range_mm a requirement check would ask of it.
power_supply
¶
power_supply(
scene,
name: str,
position: tuple,
*,
size: Optional[tuple] = None,
yaw: float = 0.0,
catalog: Optional[CatalogRef] = None,
output_a: Optional[float] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.42, 0.44, 0.47),
**attributes,
) -> Built
A DIN-rail power supply: the box <name>/body, size = (width,
depth, height), standing on position (the centre of its foot — on a
rail inside a cabinet), turned by yaw. The part (power_supply)
carries output_v / output_a — the rating scene.requirements()
checks against the current_a of the parts at its voltage.
With catalog= — the id of a power-supply spec pack, or a package
directory — a unit you can order: output_a is matched against the
ratings sold, the box takes the size the pack lists for that rating
(rules.size_mm_by_output_a, width / depth / height), and the BOM row
carries the model number, its mass and its rating.
prop
¶
prop(
scene,
name: str,
position,
*,
catalog: CatalogRef,
yaw: float = 0.0,
dynamic: bool = True,
mass_kg: float | None = None,
friction: float | None = None,
color: Optional[tuple] = None,
**attributes,
) -> str
A catalog object — a scanned mug, a cracker box, a clamp — standing
at position (x, y[, the z of the face it stands on]) turned by yaw:
the package's model as one obstacle, drawn as it ships (its textures
included) and colliding as the convex decomposition of that mesh, a
dynamic body of the pack's mass (mass_kg overrides) under physics
(dynamic=False for scenery). The model's frame need not sit in its
footprint — a scan's origin is wherever the scanner put it: the mesh is
placed so the middle of its footprint lands on (x, y) and its underside
on the face. catalog is a catalog id, an (id, revision) pair or a
package directory (a local build).
Pins one part (the catalog id and revision, the pack's category, name
and maker, the mass) and colours the obstacle with the pack's
albedo_rgb unless color is given — the flat colour the consumers
that draw no texture use (the rollout's colour pictures, a USD
without materials); the studio keeps the texture. Returns the name.
proximity
¶
proximity(
scene,
name: str,
frm: tuple,
direction: tuple = (1.0, 0.0, 0.0),
*,
sensing_range: Optional[float] = None,
body: Optional[tuple[float, float]] = None,
watch: Optional[list[str]] = None,
watch_robot: bool = False,
catalog: Optional[CatalogRef] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.42, 0.44, 0.47),
**attributes,
) -> Built
An inductive proximity switch: a beam <name> from the sensing face
at frm, sensing_range along direction — the few millimetres a
metal target must come within (4 mm unless given) — and the threaded
barrel <name>/body behind the face, body = (diameter, length) in
metres (an M12 x 47 mm barrel unless given). The beam trips on the
named objects (watch) and/or on any robot link. The part
(sensor.proximity) is pinned on the sensor.
With catalog= — the id of a proximity-switch spec pack, or a package
directory — a switch you can order: the pack's axes (size M8/M12/M18/
M30, shield, output, contact, connection …) are chosen by name,
the sensing range is the model's (sensing_range_mm), the barrel takes
the size the pack lists for the thread (rules.body_mm_by_size), and
the BOM row carries the model number and mass.
rack
¶
rack(
scene,
name: str,
size: Optional[tuple] = None,
position: tuple | tuple = (0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
levels: Optional[int] = None,
upright: Optional[float] = None,
shelf_thickness: Optional[float] = None,
yaw: float = 0.0,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
shelf_model: Optional[str] = None,
color: tuple = (0.42, 0.44, 0.47),
**attributes,
) -> Built
Shelving: size = (width, depth, height) standing on the floor at
position (its centre, x, y[, floor z]), with levels shelves evenly
spaced and the top one at height, on four corner uprights.
Adds a frame at the centre of every shelf's top face — <name>/level0 at
the bottom, upwards — which is where the parts on that shelf sit and what
a pick targets. Pins the bay (structure.rack) on the group.
With catalog= — the id of a rack spec pack, or a package directory — the
bay is one you can order: the width, depth, height and number of levels
are matched against what is sold (omit them for the catalog's defaults),
the shelves are a line of their own on the BOM with their own part number,
and a level spacing the catalog does not allow is refused.
Shelving sold as posts and shelves rather than as a bay works the same
way: a pack with an upright component and no bay puts the series on
the group line and the posts on their own, four of them, counted in the
packs the maker sells them in (rules.uprights_per_pack).
detail="full" (the default with a catalog) adds the beams under each
deck, the diagonal braces on the sides and the foot plates — decoration
that never collides, so the uprights and decks stay the only thing a
robot can hit.
remote_io
¶
remote_io(
scene,
name: str,
position: tuple,
*,
catalog: Optional[CatalogRef] = None,
di_units: Optional[int] = None,
do_units: Optional[int] = None,
points_per_unit: int = 16,
uplink=None,
place: Optional[str] = None,
yaw: float = 0.0,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.2, 0.21, 0.23),
**attributes,
) -> Built
A remote I/O station on a DIN rail: the bus coupler <name>/coupler
and its DI / DO terminal units <name>/di{i} / <name>/do{i} side by
side from position (the centre of the coupler's foot; the units run
along local +X, turned by yaw), and the I/O node <name>
(kind="remote_io", hung off uplink the way add_io_node takes it)
with a channel per point — DI0… and DO0…. The coupler is the part
(io.remote); each unit is a BOM line of its own.
With catalog= — the id of a remote-I/O spec pack, or a package
directory — a station you can order: di_units / do_units are matched
against what the pack sells, logic (PNP / NPN) picks the unit models,
the coupler and the units take the maker's widths and point counts, and
every line carries its model number and mass.
roll_container
¶
roll_container(
scene,
name: str,
size: Optional[tuple] = None,
position=(0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
yaw: float = 0.0,
detail: str | None = None,
color: tuple | None = None,
mass_kg: float | None = None,
model: str | None = None,
manufacturer: str | None = None,
**attributes,
) -> Built
A roll cage — the two-sided roll box pallet (カゴ台車) cartons are
loaded into by hand: size = (width, depth, height) outside, standing
at position (the floor point under its centre) turned by yaw. Its
two long faces (along x, the width) are open; a mesh frame stands at
each end. What collides: the base <name>/base from the floor to the
deck's top (casters and frame as one block) and the two end frames
<name>/side0 / <name>/side1, thin slabs up to the full height. The
frame <name>/deck is the deck's top centre — where the first layer
sets down. Pinned as one part (vehicle.cart) on the group. Full detail
hides the boxes inside the library's zinc-plated cage (<name>/trim/cage).
With catalog= — a roll-cage spec pack such as
makitech/roll-box-pallet/mrc-s — a cart you can order: size (or
width_mm / depth_mm) is matched against the sizes sold and a size
nobody sells is refused, the deck's height comes from the pack, and the
BOM row carries the type number, the mass and the load. Without one the
deck is at the library cage's proportion (0.243 of a 1.70 cage).
screw_feeder
¶
screw_feeder(
scene,
name: str,
position: tuple | tuple,
*,
screws: Union[Sequence[str], int],
fastener=None,
yaw: float = 0.0,
size: Optional[tuple] = None,
pick: Optional[tuple] = None,
proud: float = 0.001,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.2, 0.21, 0.23),
**attributes,
) -> ScrewFeeder
A screw presenter: a box size = (length, width, height) standing
at position (x, y[, the z of its foot]), turned by yaw, that hands
out the screws — obstacles made with bt.parts.bolt — one at a
time at a pick point on its top face.
The feeder is an indexing Source: the screws are moved into a
magazine row inside the body (its parking slots), and each
bt.seq.start(<name>) releases the next one to the pick point,
standing on its tip proud of the top face — so a program that
names the screw each step takes gets exactly one per request. The
zone sensor <name>/present over the pick point reads while a screw
stands there (the input a program waits on before picking, and that
drops when the bit lifts it away). pick is the pick point on the top
face in the body's frame (x along its length, y across), by default
centred and toward the -Y edge. The frame <name>/pick marks the
presented screw's tip, +Z up the screw.
Pinned on the device as a feeder.screw. A vibratory bowl's mechanics,
the rail, the escapement are not modelled: supply is a request and a
place.
screws may also be a count: the feeder then makes that many screws
itself (<name>/screw<i>) from fastener — a bt.assembly.Fastener,
or the pack's own thread as an ISO 4762 M
With catalog= — the id of a screw-feeder spec pack, or a package
directory — a presenter you can order: the rail size (thread_mm) is
matched against the ones sold, the body and the pick point come from
the pack, its present_s is what the bill records, and the row
carries the article number. detail="full" (the default with a
catalog) draws the body from the pack's feeder trim where it ships
one; the box underneath stays the collision.
shape_path
¶
The USD layer a library shape is drawn from — its mesh is the prim
/Shapes/<shape> — for the names in SHAPES.
shaped_box
¶
shaped_box(
scene,
name: str,
shape: str,
size: tuple,
position: tuple,
*,
quaternion=None,
color: tuple | None = None,
offset: tuple = (0.0, 0.0, 0.0),
) -> str
A decoration drawn as a library shape — the picture of a handle, a
hose, an adjuster foot beside a resident that keeps its own massing:
add_box out of collision, then appearance. With color the shape
is tinted that colour; without, it keeps the layer's finishes. Returns
the obstacle's name.
stage
¶
stage(
scene,
name: str,
size: tuple,
position,
*,
yaw: float = 0.0,
seat: float = 0.018,
plate: float = 0.016,
leg: float = 0.012,
inset: float = 0.03,
detail: str | None = None,
color: tuple = (0.2, 0.21, 0.23),
plate_color: tuple = (0.12, 0.15, 0.16),
insert_color: tuple = (0.82, 0.8, 0.74),
model: str | None = None,
manufacturer: str | None = None,
**attributes,
) -> Built
A presentation stage — the fixture a part is set on under a camera:
a top plate plate thick on four round legs of radius leg, inset
in from the corners, the whole size = (length, width, height) at
position (its underside centre) turned by yaw, with a foam insert
seat thick on the plate. The block collides as one box; in full
detail it is hidden and the plate and legs are drawn under
<name>/trim/. The frame <name>/seat is the insert's top centre.
Pins one part (fixture) on the group.
stairs
¶
stairs(
scene,
name: str,
*,
steps: Optional[int] = None,
rise: Optional[float] = None,
tread: Optional[float] = None,
width: Optional[float] = None,
position: tuple | tuple = (0.0, 0.0),
yaw: float = 0.0,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
nosing: Optional[float] = None,
rail_height: Optional[float] = None,
rails: bool = True,
legs: bool = True,
model: Optional[str] = None,
rail_model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.42, 0.44, 0.47),
tread_color: tuple = (0.5, 0.52, 0.53),
rail_color: tuple = (0.91, 0.36, 0.02),
**attributes,
) -> Built
A steel stair flight, the kind bolted against a mezzanine: steps
checker-plate treads climbing rise per step along local +x from
position (rotated by yaw), carried on a plate stringer each side and
handed by a tubular rail in safety orange.
Every tread is a walkable box, so a legged machine's footfalls snap
onto it (see the legged guide); everything else —
stringers, support legs, the handrail — is an ordinary obstacle, so an
AGV driven into the flight fails its aisle check and an arm sweeping
through the rail collides. Adds the frames <name>/foot (on the floor
at the bottom) and <name>/top (the landing edge) — author the vehicle
path's z between them — and pins the flight (structure.stairs).
Each tread overhangs the one below by nosing, the way a real one does.
That overlap is what a walking machine needs at the seam: keep it at
least twice the foot radius, or a foothold lands in the gap between
two treads and the bake refuses it by name.
With catalog= — the id of a stair spec pack, or a package directory —
the flight is one you can order: the rise, tread, width and number of
steps are matched against what is sold, the sections come from the pack,
the handrails are a line of their own on the BOM (one per side), and a
combination the maker does not sell — too steep, too shallow for the
walking rule 2 x rise + tread — is refused with the numbers.
rails=False drops the handrail (a flight against a wall);
legs=False drops the support leg under the high end, which a flight
slung between two landings — a storey of a building stair — does not
have.
table
¶
table(
scene,
name: str,
size: Optional[tuple] = None,
position: tuple | tuple = (0.0, 0.0),
*,
catalog: Optional[CatalogRef] = None,
detail: Optional[str] = None,
top_thickness: Optional[float] = None,
leg: Optional[float] = None,
yaw: float = 0.0,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
top_model: Optional[str] = None,
color: tuple = (0.42, 0.44, 0.47),
top_color: Optional[tuple] = None,
**attributes,
) -> Built
A table size = (length, width, height) standing on the floor at
position (its centre, x, y[, floor z]): a top of top_thickness on
four legs. Adds the frame <name>/top at the centre of the top face —
where a fixture or a workpiece sits — and pins one part
(structure.table) on the group. top_color paints the board apart
from the legs (a laminate top on a painted frame); color is both.
With catalog= — the id of a table spec pack, or a package directory — a
stand you can order: the sides are matched against the ones that are sold
(omit size for the pack's defaults, so position alone will do), the
profile section and the board thickness come from the pack, and where the
maker sells the board separately it lands on the BOM as its own line.
detail="full" (the default with a catalog) adds the rails under the
board and a pad under each foot — decoration that never collides, so the
legs and the board stay the only thing a robot can hit. A pack may put
the legs in from the board's edge the way the maker does
(dimensions_mm.inset_length / inset_width, to the leg centre) and
draw the whole frame, board included, from its frame trim.
tray
¶
tray(
scene,
name: str,
size: tuple,
position,
*,
yaw: float = 0.0,
seat: float = 0.018,
grips: bool = True,
detail: str | None = None,
color: tuple = (0.55, 0.57, 0.6),
insert_color: tuple = (0.82, 0.8, 0.74),
model: str | None = None,
manufacturer: str | None = None,
**attributes,
) -> Built
A parts tray: a pressed steel tray size = (length, width, height)
standing at position — the centre of its underside, a bench top —
turned by yaw, with a foam insert seat thick on it. The tray is the
box the planner checks; the insert is a picture (a set-down is refused
closer than a few millimetres to a thing the planner sees, and the
insert is what the part visibly rests on); the frame <name>/seat is
the insert's top centre, where a part sets down. Full detail draws the
tray and the insert from the shape library and a bent grip on each side
(grips), out of collision, under <name>/trim/. Pins one part
(tray) on the group.
unit_load
¶
unit_load(
scene,
name: str,
position,
*,
yaw: float = 0.0,
pallet: tuple = (1.2, 0.8, 0.144),
height: float = 0.9,
collide: bool = True,
detail: str | None = None,
) -> Built
Stock on a pallet: pallet = (length, width, height) at position
(the floor point under its centre) turned by yaw, a load height
tall on it. Two envelopes are what the aisle check meets — the pallet's
and the load's, both hidden in full detail; collide=False for stock on
a level nothing drives past. Full detail draws the timber, the courses
of cartons with their tape, a stretch-film skin and a label with its
barcode on each long side, all out of collision and inside the
envelope; the courses and the lot's colour follow from name, so a
replay draws the same stock. Stock is not a purchase: nothing is
pinned.
vise
¶
vise(
scene,
name: str,
position: tuple | tuple,
*,
yaw: float = 0.0,
jaw_width: float = 0.125,
opening: float = 0.06,
max_opening: float = 0.15,
jaw_height: float = 0.04,
jaw_thickness: float = 0.03,
body_height: float = 0.06,
body_length: float = 0.36,
catalog: Optional[CatalogRef] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
color: tuple = (0.46, 0.47, 0.49),
**attributes,
) -> Built
A machine vise standing on a table top at position (x, y[, the
table's top z]): the body, a fixed jaw and a moving jaw set opening
apart, the jaws clamping along local Y (the fixed jaw on +Y, the
screw end trailing off to -Y) before yaw. Adds the frame
<name>/jaw at the centre of the jaw floor between the jaws — where
the workpiece sits, jaw_width wide along X and opening across — and
pins the vise (fixture.vise).
Clamping is a signal, not a motion: the jaws stand where the part
goes and the cell's program says when it is held (a machine-tending
handshake's clamp — see bt.tending). An opening beyond
max_opening is refused with the numbers, the way a size nobody
sells is.
With catalog= — the id of a vise spec pack, or a package directory —
a vise you can order: jaw_width is matched against the ones sold,
the jaw and body figures and the maximum opening come from the pack,
and the BOM row carries its article number and mass.
wall
¶
wall(
scene,
name: str,
path: Sequence[tuple],
*,
height: float = 2.7,
thickness: float = 0.12,
base_z: float = 0.0,
closed: bool = False,
openings: Sequence[Sequence[float]] = (),
head: float = 2.1,
detail: Optional[str] = None,
color: tuple = (0.62, 0.6, 0.56),
trim_color: Optional[tuple] = None,
model: Optional[str] = None,
manufacturer: Optional[str] = None,
**attributes,
) -> Built
A partition along path (floor corners, metres): thickness thick,
height tall, standing off base_z. closed joins the last corner back
to the first, so a four-corner path is a room.
openings=[(edge, centre, width), ...] cuts a doorway width wide,
centred centre metres along that edge, and spans the wall over it —
the pier each side and the head above are ordinary obstacles, so a
machine driven at the pier fails its aisle check while one sent through
the opening passes. A fourth element sets that opening's clear height
(head otherwise); at or above the wall's own height it is a gap
through it, with nothing over. Each one adds the frame
<name>/opening{edge}_{i} on the floor at its centre, facing along the
wall — that is where a route is authored through it.
Corners get a thickness square column so two runs meet square, and
detail="full" adds a skirting to each face and a lining round each
opening as decoration (drawn, never collided). Pins one part
(structure.wall) carrying the run's length, height and thickness.
bt.parts.wall(scene, "corridor/north", path=[(0, 2.4), (18, 2.4)],
height=2.7, openings=[(0, 6.0, 0.9), (0, 11.0, 0.9)])
workpiece
¶
workpiece(
scene,
name: str,
position: tuple | tuple,
*,
catalog: CatalogRef,
yaw: float = 0.0,
cover_at: Optional[tuple | tuple] = None,
detail: Optional[str] = None,
color: tuple = (0.5, 0.51, 0.53),
cover_color: tuple = (0.62, 0.63, 0.66),
**attributes,
) -> Workpiece
A two-part assembly from a workpiece spec pack — a housing on its
fixture at position (x, y[, the z of its underside]) turned by yaw,
and its cover waiting at cover_at (the same point when omitted:
seated). The pack's components size them (housing: length, width,
height; cover: length, width, thickness, boss_diameter, boss_height;
dowel: diameter, proud) and its mounting declares the joint: the
housing's flange face with its threaded holes and dowel pins, the
cover's mount face with its clearance holes, the screws. The pins
stand on the housing where the flange face's locators say. Frames:
<name>/seat (the housing's top face centre, +Z up — the mating
plane) and <name>/stock (where the cover waits). Everything is
pinned to the pack, dowels included (two lines with a count).
bt.assembly.joint(catalog=...) reads the same pack for the holes.
detail="full" (the default) draws the housing and the cover as the
prims the pack ships for them (components[].visual) — the casting
and the machined cover — bound to the parts, so they travel with them;
the boxes underneath stay what the cell checks.