Timeline¶
The baked result of a sequence: what every robot did, when every step ran, how every signal moved, and where every object was — for one cycle.
tl = scene.simulate_sequence("cycle")
tl.duration # cycle time, seconds
tl.step_span("feed").duration # one step's baked interval
tl.signal("eye").rising_edges() # when the beam broke
tl.min_clearance() # tightest approach over the whole cycle
tl.export_usd("cycle.usda", fps=60)
The bake is deterministic — the same scene produces a bit-identical timeline every run — which is what makes these values usable as regression assertions.
SequenceTimeline
¶
A baked sequence rollout: per-robot joint tracks, grasped-object motion, signal waveforms, and step spans (the timing chart).
branches
property
¶
The path the bake took through branching steps, in resolution
order: (sequence, step name, arm index). Untaken arms have no
spans — this is how a timeline says which way it went.
contacts
property
¶
Touch episodes of a physics bake, in opening order: dicts with
a, b (scene names; robot/link for an arm part), start,
end (s), position (world, where the touch began) and
peak_force (N, the episode's largest total contact force).
Empty on a kinematic bake. Only pairs involving a dynamic body
are recorded — "part hit the stopper at t=5.6 s with 8 N" is one
entry here.
physics
property
¶
The physics engine this bake stepped under ("rapier"), or None
for the purely kinematic bake. A physics bake is deterministic per
machine and build — not the cross-platform bit-identity the
kinematic bake guarantees.
scenario
property
¶
The scenario this bake ran under; None is the unmodified scene
(baseline).
sequences
property
¶
Names of the sequences this timeline was rolled from, in scan
order — the programs to_script can export.
trajectory
property
¶
The sole robot's cycle track (see robot_trajectory; with several
robots this is ambiguous — name one).
base_pose
method descriptor
¶
Where a mounted robot's base was at time t — None for a robot
bolted to the floor, whose base is a scene constant.
busy_seconds
method descriptor
¶
Seconds a robot spent in motion (overlapping move intervals merged).
carve_stock
method descriptor
¶
carve_stock(
stock,
robot=None,
tcp_link=None,
voxel_size=0.001,
cutter_radius=0.004,
cutter_length=0.03,
dt=0.01,
)
Carves stock with the cutter swept along this cycle: a voxel
subtraction in the stock's frame, returning the machined part as
a mesh plus removed/remaining volume. Presentation and numbers —
the cut can never contradict the plan in a kinematic world.
conveyor_stalls
method descriptor
¶
Stretches where a running conveyor drove under a tracked object
that made almost no progress along the belt — a queue seating
against its stopper (by design) or a genuine jam (not): dicts
with object, device, start, end. The detector reports
arrest; only the author knows intent.
diff
method descriptor
¶
Compares this bake with a controller trace (bt.trace.load — a
CSV path / text, a {name: [(t, value), ...]} dict, or a Trace)
edge by edge, by name: matched edges within tolerance seconds,
missing ones (baked, never seen), extra ones (seen, never baked).
align_on= names a signal whose first rising edge sets the trace's
clock against the bake's; signals= picks the names to judge;
io= renames binding tags to point names. Returns a
bt.trace.TraceDiff (ok, signals, findings(), to_markdown(),
to_json()) — the offline commissioning check.
export_handshake_spec
method descriptor
¶
Writes handshake_spec() to path (Markdown).
export_script
method descriptor
¶
export_script(
path,
sequence=None,
dialect="urscript",
name=None,
inputs=None,
outputs=None,
speed_scale=1.0,
blend_radius=0.0,
tcp_speed=0.25,
tcp_accel=1.2,
move_to_start=True,
node=None,
io=None,
)
Writes to_script output to path (see there for the semantics).
export_usd
method descriptor
¶
Bakes the whole cycle to a USD animation layer (see
Scene.export_usd): every robot + every obstacle, with grasped
objects riding, releasing, resting — and handed over — exactly as
simulated. A sole robot exports under the historical Robot prim;
with several, each lands at /World/<sanitized instance name>.
The extension picks the serialization: .usda text, .usdc/.usd
binary crate at roughly half the size.
start/end clip the export to a window of the cycle. A line's
full run is mostly repetition — one steady-state takt carries the
whole story at a fraction of the bytes, which is what makes a
line recording shippable at all.
feed_report
method descriptor
¶
Feed adherence of a toolpath the cycle ran (StartToolpath).
toolpath=None means the only one; name it when the cycle cuts
several.
footfalls
method descriptor
¶
The steps a walking robot's legs took, as (leg, lift, land,
(x, y, z)) in landing order: the foot left its previous anchor at
lift and has stood at the position since land. Empty unless the
robot walks its vehicle (a bt.Gait on its mount).
grasp_report
method descriptor
¶
grasp_report(
min_touches=2,
grip_force_n=None,
mu=None,
payload_kg=None,
safety_factor=2.0,
max_slip_m=0.01,
)
Every grasp this bake performed — one dict per attach…release
stretch, annotated from the physics contact record and checked
against what numbers are at hand. Fields: object, robot,
link, start, end, held_to_end, touched (tool link →
peak contact force N around the attach; empty on a kinematic
bake), released_touching (the release happened inside the
squeeze — author "open, then detach"), mass_kg (as the bake
resolved it; None without physics authoring), max_accel
(largest carry acceleration, m/s²), slip_m (how far the part
strayed from riding its carrier — friction holds under a gripper
drive only, None on welds), and checks:
touch— at leastmin_touchesdistinct tool links touching at the attach (skipon a kinematic bake).release—warnwhen released inside the squeeze.payload— grasped mass ≤payload_kg, when both are known.grip_force—grip_force_n × mu × touching surfaces ≥ mass × (g + max_accel) × safety_factor, when force, mu, and mass are known (on a kinematic bake two surfaces are assumed).hold— a friction hold's measuredslip_mstays withinmax_slip_m(skipon welds and kinematic bakes).
The numbers default from what the cell already knows: a catalog
gripper welded on with attach_tool supplies grip_force_n (its
grip_force_min_n — the weakest stated setting — else
grip_force_max_n) and payload_kg from its own specs, and mu
defaults to the most slippery authored pairing of the touching
links' materials and the part's (min rule — conservative for a
holding check). Explicit arguments always win; the values used are
reported back as grip_force_n / payload_limit_kg / mu.
handshake_spec
method descriptor
¶
The handshake specification of this bake as Markdown: every line
between controllers — handshake signals, robot start / done /
program handshakes, device command and in-position lines — with
direction, both ends (node and channel when bound), the steps that
write and wait on it, and its waveform (high spans, or the robot's
start pulses and busy spans). The draft of the robot ⇔ PLC
interface sheet, per scenario. io= projects a newer assignment
onto a bake made before the wiring.
min_clearance
method descriptor
¶
The tightest robot-to-environment approach over the cycle, sampled
every dt seconds against the scene the timeline was baked from
(carried and conveyed objects replay their baked motion; robot-robot
contact is already a hard rollout error). Raises when the cell has
nothing to measure.
moves
method descriptor
¶
A robot's move intervals as (label, start, end) — the intervals a
motion (by name) or ramp drove it.
object_pose
method descriptor
¶
World pose of a grasped/tracked object at time t.
object_visible
method descriptor
¶
Whether a tracked object should be drawn at t. False only while
it is stowed — waiting in a magazine, or taken off the line.
paint_report
method descriptor
¶
paint_report(
target,
robot=None,
tcp_link=None,
gate=None,
standoff=None,
max_incidence=Ellipsis,
max_range=None,
dt=0.01,
)
Checks what the robot actually did against the teaching rules of a
spray program: every dt while the gun was spraying — gate high
(or no gate) and inside a feed stroke, the same two triggers
spray_coat uses — the TCP's spray axis is cast at target and
the standoff and incidence read off the hit. standoff is the
acceptable band in meters, max_incidence the steepest acceptable
angle in radians. at on the issues is timeline seconds.
The baked twin of Scene.check_paint: that one checks the
authored path before any robot is involved; this one includes
whatever the solver did with the free spin and the tolerance it
was given.
process_spans
method descriptor
¶
The (start, end, brush) intervals a robot's toolpath moves spent
spraying — the program's own process trigger, as opposed to
rapids, gun-off moves, and the approach planned in from wherever
the robot stood; brush is None in a program that names none.
Merged, in time order. Empty when the robot ran no toolpath: then
there is no program to say when the process was on, and
spray_coat / paint_report take the whole timeline as process
time.
robot_busy
method descriptor
¶
Intervals a robot was driven by a motion, ramp or toolpath, merged where they touch — the "busy" contact a robot controller would show a PLC, synthesized from the bake (a robot has no signal lane). Robot defaults to the scene's first.
robot_trajectory
method descriptor
¶
A robot's cycle joint track as a [Trajectory] (CSV/JSON export,
joint access). Step boundaries land in segment_ends.
sample
method descriptor
¶
A robot's joint positions at time t (clamped to the cycle).
settled_at
method descriptor
¶
When the object came to rest for good — the start of its trailing
hold — or None while it was still moving (or held, or never
tracked) at the horn. On a physics bake this is the moment the
engine put the body to sleep for the last time.
signal
method descriptor
¶
The named waveform lane — an internal signal, a sensor, or a device's running state.
spray_coat
method descriptor
¶
spray_coat(
target,
applicator=None,
robot=None,
tcp_link=None,
patch_size=0.005,
dt=0.01,
gate=None,
spec=None,
max_incidence=Ellipsis,
facing=None,
facing_tolerance=Ellipsis,
occlusion=True,
style="auto",
paint_color=None,
substrate=None,
)
Sprays applicator along this cycle and reports the film left on
target: a thickness map as a colored mesh plus the numbers a
paint engineer reads — in-spec area, holidays, paint used.
What sprays comes from the program: a toolpath whose strokes name
brushes (scene.define_brush) sprays each with that brush's
applicator, flow and trigger timing, and applicator may be left
out; one that names none sprays every feed move with applicator
(the dict bt.paint.applicator(...) builds), which is then
required. The applicator's footprint is calibrated geometry, not
fluid dynamics: no air
flow, no electrostatics, so the electrostatic wrap around edges is
not modeled and the absolute micrometers are only as good as the
pattern fed in. Relative structure — lap streaks, thick corners,
the film left by a stroke that lost speed — is the robust part,
because the walk runs on the baked trajectory.
Two triggers decide when paint flows, and both must agree: gate
names the PLC's enable signal (without one it is taken as always
on), and the program's own trigger is the feed strokes of the
toolpath the robot was running — rapids and the approach planned
in from wherever the robot stood never spray, however the enable
was authored. A timeline that ran no toolpath has no program to
say when the process was on, so there the enable alone decides.
spec is the acceptable film band in meters. style picks how the
film map is coloured: "amount" (a sequential ramp, light to dark
— how much paint; in paint_color if given, so it looks like the
coat going on) or "spec" (diverging over the band: neutral on
target, blue thin, red thick — the verdict); "auto" is "spec"
when a spec was given. Bare patches wear substrate, or the
target's own colour.
Statistics run over the surface the gun addressed — in range and
within max_incidence of square on. A part's back face is not a
holiday, and neither is the rim of a panel sprayed from above,
which would otherwise swamp the film map with one grazing band.
Deposition ignores the limit, so paint stays conserved.
facing names the job by the way it faces — a world direction,
with only patches whose normal lies within facing_tolerance of
it counted ((0, 0, 1) for "the top"). Without it the addressed
set depends on the path: a rim swings into the mask as the gun
turns around past the edge, so lengthening the overtravel quietly
changes every denominator. Name the face for numbers that compare
across programs.
step_span
method descriptor
¶
The baked interval of the named step (assertion-friendly view of
one step_spans row).
to_script
method descriptor
¶
to_script(
sequence=None,
dialect="urscript",
name=None,
inputs=None,
outputs=None,
speed_scale=1.0,
blend_radius=0.0,
tcp_speed=0.25,
tcp_accel=1.2,
move_to_start=True,
node=None,
io=None,
)
Renders one program of this timeline as a vendor robot script —
the same steps that drove the simulation, with real I/O: inputs
maps signal/device/robot names to digital input ports (level
waits), outputs maps signal/device names to digital output ports
(coil writes). Timers become sleeps; moves are the rollout's own
planned sparse paths.
The program is named after the sequence (name overrides). The
sequence must drive exactly one robot — a multi-robot cell exports
one script per program. Approximations (unmapped device commands,
waits that ran beside a move in simulation) are raised as Python
warnings; what cannot be expressed at all (any_of waits,
conveyor tracking) raises ValueError.
utilization
method descriptor
¶
Fraction of the cycle a robot spent moving, 0..1 — the line-balancing number. The bottleneck is whoever sits near 1, and this is what predicts where moving a spot lands the takt.
utilizations
method descriptor
¶
{robot: utilization} for every robot on the timeline.
vehicle_airborne
method descriptor
¶
Seconds the vehicle spent off its starting ground: every span that
moves it, plus every hold above the altitude it started at — exact,
the spans are closed form. For an aerial machine this is the
motor-on time a declared flight_time_min must cover (hover at a
station counts, waiting on the pad does not); for a ground machine
it is simply its driving time. A vehicle that never drove flew 0 s.
with_trigger_signal
method descriptor
¶
The timeline with the effective spray trigger — the enable signal
AND the program's own (feed strokes, brush lead/lag included) —
written as signal name, replacing any lane of that name. What a
timing chart shows as "spraying", and what a spray-cone effect
(scene.add_spray_cone) should bind to; declare name with
scene.define_signal first so the effect can be bound. Nothing
else about the timeline changes.
Span¶
Returned by SequenceTimeline.step_span:
one step's interval, in a form that reads well in an assertion
(assert tl.step_span("feed").end <= 2.0).
Span
¶
SignalTrack¶
Returned by SequenceTimeline.signal. One
boolean waveform lane — an internal signal, a sensor, or a device's running
state — with edge and duty queries on top of it.
SignalTrack
¶
A signal/sensor/device waveform lane on a baked timeline.
kind
property
¶
Where the lane comes from: "signal" (internal relay, or a lane
synthesized under a signal's name), "sensor" (input) or
"device" (running / moving output).
high_spans
method descriptor
¶
(start, end) intervals the lane is ON; an interval still open at
the cycle end closes at duration.
rising_edges
method descriptor
¶
Times the lane turns ON (the initial level at 0 is not an edge).
Clearance¶
Returned by
SequenceTimeline.min_clearance: the
tightest robot-to-environment approach over the cycle, with the time and the
pair it happened at. It compares against plain floats, so
assert tl.min_clearance() > 0.05 works directly.