Results¶
The result objects a generator writes, their Layout, the capability protocols the
runtime utilities accept, and the check they run; Results: Track, GateSequence, Centerline explains how to read
them. Every result holds per-env arrays ([E], such as valid) and
per-point arrays ([E * stride]). Track, GateSequence, Layout and the
protocols are also importable from track_gen, and track_gen.plugin.Layout is the
same class as track_gen.results.Layout.
The result objects: Track, GateSequence, Centerline, their
Layout, the capability protocols and check_source().
Every result is flat, fixed-stride device storage: per-point arrays [E * stride]
(NaN past count[e]; int32 -1) and per-env arrays [E], described by a
Layout (num_envs, stride, device, closed). Each result class
offers:
validate(need=()): check every field against the layout (host only); a hand-built result with a mismatched field is rejected with a message naming the field and the expected shape;view(e0, e1): a zero-copy env slice (kernel-safe: every kernel indexes from the view’s element 0), e.g.TrackGenerator(..., out=big.view(0, 4))for mixed batches;copy_from(src, *, stream=None, ctx=None): stream-ordered copies, no allocation, capture-safe (the hot-path snapshot);clone(*, stream=None): an owned deep copy (allocates: cold);alloc(layout, *, attributes=None): a fully allocated result in the “no track yet” state (cold).
Each protocol is a capability a family of consumers shares, and each consumer checks
the subset of it it reads (check_source(..., members=...)), so a utility accepts any
object with those members (a Track, a Centerline, a user’s own object):
HasCenterline (TrackLocalizer, localize.curvature / speed_profile),
HasBand (CollisionChecker, PropSampler, CheckpointSampler,
HeightFieldBaker), HasGates (a gates-mode Course’s course line),
HasGateFrames (its frame checker, CheckpointSet.from_gates) and
HasGeneration (generation-aware consumers; checked together with another protocol:
check_source(obj, (HasCenterline, HasGeneration), ...)), HasValidity (the per-env
valid flags) and HasCheckpoints (an ordered checkpoint set: what
ProgressTracker reads). A shipped protocol never changes: a new
capability is a new protocol, composed with the existing ones. The library never relies
on isinstance against them (their runtime semantics differ across Python versions):
consumers check their source with check_source().
Optional reads: a consumer that reads a member only when the source has
it (valid: the invalid-env sentinels; generation: the generation-aware
self-reset) names it in check_source(..., optional=...): a present member is checked
like a required one (same messages), a missing (or None) one is skipped.
- class Layout[source]¶
Bases:
objectThe shape of a batch: the envs, the per-env row capacity, the device and the topology. Handed to
Params.validate,Stage.capacityand theStageBuilder, and carried by every result (Track.layout,GateSequence.layout,Centerline.layout).track_gen.results.Layout,track_gen.Layoutandtrack_gen.plugin.Layoutare this class.- stride¶
The per-env row capacity (an int
>= 1):N_maxfor aTrack(and a track stage),max_gatesfor aGateSequence(and a gate stage), and for aCenterlineits own capacity (max_gates * samples_per_gatefor a gates-modeCourse’sCourseLine.centerline). A channel’s own row stride isStageBuilder.stride_of.- Type:
- device¶
The device string, stored AS GIVEN (
"cuda"stays"cuda"). The layouts TrackGen makes (the planner,alloc,view, an inferred one) store the canonicalstr(wp.get_device(d))("cuda:0"), so==holds between them; the library’s own checks compare the canonical device, so a hand-setLayout(E, S, "cuda")matches"cuda:0".- Type:
- closed¶
Whether the loops are closed. Only
Trueis supported in 0.x (aBatchSpec(closed=False)is refused by the planner, a source withclosed=Falseby every utility).- Type:
- Raises:
TypeError – a non-integer (or bool)
num_envs/stride, a non-strdevice, a non-boolclosed.ValueError –
num_envs < 1orstride < 1.
- __init__(num_envs, stride, device, closed=True)¶
- classmethod __new__(*args, **kwargs)¶
Tracks and gate sequences¶
- class Track[source]¶
Bases:
objectFinal batched result of the track generation pipeline.
All boundary arrays are index-aligned:
outer[i],center[i]andinner[i]share a single cross-section normal.half_width[i]is the band’s half-width there (‖outer[i] - center[i]‖in plan view). Fields arewp.array; convert at the boundary via the wp bridge.Warning
TrackGenerator.generate()returns the SAMETrackinstance on every call and overwrites its buffers in place. A reference held across twogenerate()calls will see mutated data. CallTrack.clone()to obtain a fully-owned deep copy before the next call (orcopy_frominto a preallocatedTrack.allocresult: no allocation, capture-safe).Methods (see
track_gen.results):validate()(check every field against the layout),view()(a zero-copy env slice, e.g.out=of a mixed batch),copy_from()(stream-ordered copies, no allocation: the hot-path snapshot),clone()(an owned copy; allocates) andalloc()(a fully allocated result).- outer¶
Flat
[E * N_max]vec3fouter boundary points. Each real point’szfollows the configuredTrackGenConfig.z_profile— 0 only for the default"flat"profile atz_base=0— and shares thecenterpoint’s altitude at the same index (level cross-sections; see 2.5D tracks). Reshape viawp.to_torch(...).view(E, N_max, 3). Points ati >= count[e]are NaN-padded (NaN xy; z carries the flat path’sz_base, 0 by default).- Type:
wp.array
- center¶
Flat
[E * N_max]vec3fcenterline points.zfollows the configuredTrackGenConfig.z_profile(seeouter). Reshape viawp.to_torch(...).view(E, N_max, 3). Index-aligned withouterandinner;‖outer[i] - center[i]‖gives the per-point half-width (an XY-plane distance: level cross-sections share a Z, so the vertical component cancels). Points ati >= count[e]are NaN-padded.- Type:
wp.array
- inner¶
Flat
[E * N_max]vec3finner boundary points.zfollows the configuredTrackGenConfig.z_profile(seeouter). Reshape viawp.to_torch(...).view(E, N_max, 3). Points ati >= count[e]are NaN-padded.- Type:
wp.array
- tangent¶
Flat
[E * N_max]vec3funit tangent vectors at each centerline point. For the default"flat"profile this is the planar tangent (z = 0) from central differences over the 2D centerline; for a non-flatz_profileit is instead a true 3D central difference over the LIFTED centerline (see 2.5D tracks). NaN-padded pastcount[e].- Type:
wp.array
- normal¶
Flat
[E * N_max]vec3funit left-normals at each centerline point — still the planar left-normal, alwaysz = 0, computed asnormal = (-tangent2d.y, tangent2d.x, 0)(the PLAN-VIEW tangent rotated +90° about +z) BEFORE the elevation lift. For a non-flatz_profilethis predates the 3D recompute described undertangent: the two fields are no longer literally related by that rotation formula (normal’s XY direction still matchestangent’s XY projection, buttangentis unit-length in 3D, so its XY projection alone is sub-unit and rotating it will not reproduce a unitnormal). Which boundary it faces is winding-dependent (seewinding): it points towardouterfor clockwise loops and towardinnerfor counter-clockwise loops. Theouter/innersplit itself is winding-agnostic (assigned by signed-area magnitude), so useouter/inner— not the normal’s sign — to identify the boundaries. NaN-padded pastcount[e].- Type:
wp.array
- arclen¶
Flat
[E * N_max]float32cumulative arc length along the centerline at each point. For the default"flat"profile this is the plan-view (2D) arc length; for a non-flatz_profileit is the true 3D arc length of the LIFTED centerline (strictly >= the plan-view length whenever the profile is non-constant; see 2.5D tracks). Reshape viawp.to_torch(...).view(E, N_max). NaN-padded pastcount[e].- Type:
wp.array
- length¶
[E]float32total arc length (perimeter) of each track’s centerline loop — plan-view for the default"flat"profile, true 3D length otherwise (seearclen).- Type:
wp.array
- valid¶
[E]int32environment validity flags (0 or 1). A track is valid when: turning number ≈ 1, no NaN points, width floor exceeded everywhere, minimum thickness ≥(1 − relax_tol) * half_width, the track was not truncated atN_max(seetruncated), and (whenvalidity_border_check=True) zero border self-intersections. Convert viawp.to_torch(...).bool().- Type:
wp.array
- count¶
[E]int32real point counts, derived from constant-spacing resampling ascount[e] = floor(perimeter / spacing) + 1, capped atN_max. All other arrays are NaN-padded for indicesi >= count[e].- Type:
wp.array
- winding¶
[E]float32signed loop winding:+1.0for a counter-clockwise centerline,-1.0for clockwise (the sign of the loop’s signed area), and0.0for degenerate/empty loops. Winding is generator-dependent (bezier and hull wind clockwise; polar, voronoi and checkpoint wind counter-clockwise), so this field lets a consumer orient itself: for a CCW loopouterlies to the right of increasing arc length, for a CW loop to the left.- Type:
wp.array
- truncated¶
[E]int32N_max truncation flags (0 or 1), written on device by the constant-spacing resample.1means the loop needed more thanN_maxpoints (floor(perimeter / spacing) + 1 > N_max), socount[e]was clamped toN_maxand the tail of the loop was dropped; such envs always havevalid == 0. IncreaseN_max(orspacing) if any are set.TrackGeneratoralways allocates it;Noneon aTrackbuilt elsewhere (e.g. the standaloneinflate_warppath).- Type:
wp.array or None
- generation¶
[E]int32: the seed epoch (TrackGenerator.seeds.epoch) each env’s current track was built at.0until the first advance. It is the epoch, not a change counter: a reseed at the same epoch (rng.set_seeds_warp,Course.generate(seeds=...)) does not change it, and afterseeds.reset_epoch()the same values come back. Only while epochs are advanced and nothing reseeds or resets them does it change exactly when an env gets a NEW track (generate(advance=True, ...)/Course.regenerate(advance=True, ...)), so that comparing it on device to a stored copy detects every regeneration.TrackGeneratoralways allocates it;Noneon aTrackbuilt elsewhere.- Type:
wp.array or None
- fail_mask¶
[E]int32per-env fail bitmask: bitiset means checkifailed (fail_bitsnames the bits: the built-in checks’ 0-7 aregenerator,turning,finite,thickness,w_floor,border,grade,truncation; plugin checks own 16-30). When it is notNone,valid[e] == (fail_mask[e] == 0).TrackGeneratoralways allocates it;Noneon aTrackbuilt elsewhere (e.g. the standaloneinflate_warppath).- Type:
wp.array or None
- fail_bits¶
name -> bit indexof every bit offail_maskthe pipeline assigns (TrackGenerator.program.fail_bits); the border / grade bits are named even when their check is off (then never set). Empty on aTrackbuilt elsewhere.
- half_width¶
Flat
[E * N_max]float32half-width of the band at each centerline point (the offset’s:‖outer[i] - center[i]‖in plan view), NaN pastcount[e]. The constanthalf_widthof the config on every real point at constant width (width.constant); the per-point width of a width stage or a generator that provides one otherwise.TrackGeneratoralways allocates it;Noneon aTrackbuilt elsewhere.- Type:
wp.array or None
- attributes¶
The per-point attributes the pipeline exports (
StageBuilder.write(..., export=True)), keyed by the channel name without its domain prefix (raw.acme.surface_id->"acme.surface_id"): flat[E * N_max]arrays of the attribute’s dtype, carried to the final points with itsinterppolicy, NaN (floats) /-1(int32) pastcount[e]. Stable pointers for the generator’s lifetime. Empty unless a stage exports one (TrackGenerator.program.attributesdescribes them).- Type:
Mapping[str, wp.array]
- layout¶
The batch’s
Layout(num_envs,stride=N_max,device,closed), set on everyTrackTrackGen makes (a generator’s result, aview(),clone(),alloc());Noneon one built by hand (validate()infers it).- Type:
Layout or None
- validate(need=())¶
Check every field of this result against its layout; return the layout.
The layout is
layoutwhen set, else inferred (num_envsfromcount,stridefrom the first per-point field, the device ofcount,closed=True; nothing is mutated). Then every array field that is notNonemust be a contiguous 1-D array of its dtype,[E * stride](per point) or[E](per env), on the layout’s device (compared canonically:"cuda"=="cuda:0"), and everyattributesentry a contiguous[E * stride]float32 / int32 / vec2f / vec3f array on that device. Host only (a few microseconds): no device work, safe inside a capture.- Parameters:
need – Field names that must not be
None(an optional field a consumer reads).- Returns:
The stored or inferred
Layout.- Raises:
ValueError – the first field that does not match, naming it and the expected shape (e.g.
Track.inner: expected a contiguous [3072] vec3f ([E*stride] = [8*384]) array on cpu, got shape (3064,) vec3f on cpu); a field ofneedthat isNone; acountthat is not an array.
- Return type:
- view(e0, e1)¶
A zero-copy view of envs
[e0, e1)of this result.Every array is a slice of this result’s array (per point
[e0 * stride : e1 * stride], per env[e0 : e1]): the same memory, read and written in place, and kept alive by the view.Nonefields stayNone;attributesare sliced alike;fail_bitsis shared;layoutisLayout(e1 - e0, stride, device, closed). A view is a result like any other: every TrackGen kernel indexes it from its own element 0, so it can be generated into (TrackGenerator(..., out= big.view(0, 4)): mixed batches), consumed by the utilities, copied, cloned and viewed again. No device work and no allocation: callable inside a capture.- Raises:
IndexError – unless
0 <= e0 < e1 <= num_envs.TypeError – non-integer indices.
ValueError – this result does not validate (
validate()).
- Parameters:
- copy_from(src, *, stream=None, ctx=None)¶
Copy every field this result holds from
src(same class, same layout).One stream-ordered device copy per held field (a field
Nonehere is skipped) and perattributeskey of this result (srcmay hold more keys). No allocation and no host sync, so it is the hot-path form of a snapshot (copy into a preallocatedalloc()result) and it records into a caller’s capture (memcpy nodes). Host metadata (fail_bits,layout) is not copied.t.copy_from(t)is a no-op.The copies run on
ctx, elsestream=> an ambientLaunchContext.scope> the stream that producedsrc(the generator’s constructorstream=) > an enclosing torch capture > Warp’s current stream.copy_fromonly knows the producer’s DEFAULT stream: pass the stream you generated on (or order the streams with events) when a generation ran elsewhere.- Parameters:
src – A result of the same class (
Track/GateSequence/Centerline).stream – Optional
wp.Stream(or"torch").ctx – Optional
LaunchContext(not withstream=).
- Raises:
TypeError –
srcis not of this result class;stream=andctx=together.ValueError – either side does not validate; the layouts differ (canonical device); a field held here is
Noneinsrc; an attribute key here is missing fromsrcor has another dtype; a partial overlap of a field with its source.
- Return type:
None
- clone(*, stream=None)¶
A fully-owned deep copy (new memory for every held field and attribute).
COLD: allocates and blocks every call (use
copy_from()into a preallocatedalloc()result on a hot path). Allocated and copied on Warp’s CURRENT stream (wherewp.emptyallocates), then a host wait on that stream: the clone is complete when it returns, so it is safe to read or write on ANY stream right away (.numpy(), a utility,copy_fromon a generator’s stream). When the result was produced on another stream (stream=, else an ambient scope, else the generator’s constructorstream=), Warp’s current stream first waits on it.Nonefields stayNone,attributesare copied,fail_bitsis shared (an immutable mapping),layoutis set; the class (a subclass) is kept.- Parameters:
stream – The stream that PRODUCED this result (
wp.Streamor"torch"), e.g.track = gen.generate(stream=s, sync=False); snap = track.clone(stream=s).- Raises:
track_gen.exec.CaptureError – inside any capture (Warp CPU / CUDA or torch), before allocating; inside a graph,
copy_frominto a preallocatedalloc()result instead.ValueError – this result does not validate (a malformed hand-built result).
- classmethod alloc(layout, *, attributes=None)¶
A result with every field allocated, in the “no track yet” state.
Per-point fields (and attributes) hold their padding (NaN;
-1for int32),count/valid/truncated/generation/fail_maskare 0,length/winding0;layoutislayoutwith the canonical device;fail_bitsis empty. Allocation and fills run on Warp’s CURRENT stream (likewp.full), then a host wait on it: the result is complete when it returns, so it can be read or written on ANY stream right away (snap.copy_from(track)on a generator’s stream,TrackGenerator(..., out=big.view(0, 4), stream=s)). COLD: allocates and blocks.- Parameters:
- Raises:
TypeError –
layoutis not aLayout; an attribute dtype outside the four;attributeson aCenterline.ValueError – an attribute key that is not
"<package>.<name>".track_gen.exec.CaptureError – inside a capture (before allocating).
fail_maskandfail_bitssay why an env is invalid (its fail bits): the bit table isBUILTIN_FAIL_BITSplus the pipeline’s plugin checks (see Fail bits).half_widthis the band’s per-point half-width, andattributesthe per-point attributes the pipeline exports (see Per-point attributes in the result).layoutisNoneon aTrackbuilt by hand (Layout).- __init__(outer, center, inner, tangent, normal, arclen, length, valid, count, winding, truncated=None, generation=None, fail_mask=None, fail_bits=<factory>, half_width=None, attributes=<factory>, layout=None)¶
- Parameters:
outer (array)
center (array)
inner (array)
tangent (array)
normal (array)
arclen (array)
length (array)
valid (array)
count (array)
winding (array)
truncated (array | None)
generation (array | None)
fail_mask (array | None)
half_width (array | None)
layout (Layout | None)
- Return type:
None
- classmethod __new__(*args, **kwargs)¶
- class GateSequence[source]¶
Bases:
objectBatched fixed-stride gate result returned by
GateGenerator.Gate pose arrays are flat
[E * max_gates]vec3fbuffers; reshape viawp.to_torch(...).view(E, max_gates, 3).count[e]gives the real gate count for environmenteand slotsi >= count[e]are NaN-padded (any NaN component marks a padded slot). Each real slot’szfollows the configuredGateGenConfig.z_profile; it is 0 only for the default"flat"profile atz_base=0.Warning
GateGenerator.generate()returns the SAMEGateSequenceinstance on every call and overwrites its buffers in place. A reference held across twogenerate()calls will see mutated data. CallGateSequence.clone()to obtain a fully-owned deep copy before the next call.Methods (see
track_gen.results):validate()(check every field against the layout),view()(a zero-copy env slice, e.g.out=of a mixed batch),copy_from()(stream-ordered copies, no allocation),clone()(an owned copy; allocates) andalloc()(a fully allocated result).- position¶
Flat
[E * max_gates]vec3fgate centres. Reshape viawp.to_torch(...).view(E, max_gates, 3). Slotsi >= count[e]are NaN-padded.- Type:
wp.array
- tangent¶
Flat
[E * max_gates]vec3funit tangent vectors at each gate centre. NaN-padded pastcount[e].- Type:
wp.array
- forward¶
Flat
[E * max_gates]vec3funit pose forward (x-axis oforientation): the physical gate-plane normal used for pass detection; equalstangentforfull_tangentand for planaryaw_onlygates, the horizontal projection oftangentfor slopedyaw_onlygates; NaN-padded pastcount[e].- Type:
wp.array
- orientation¶
Flat
[E * max_gates]quatfgate poses (wp.quatf(x, y, z, w)): the roll-free frame with local x = gate forward, y = left, z = up. NaN-padded pastcount[e].- Type:
wp.array
- half_size¶
Flat
[E * max_gates]float32square-opening half-extents (0.5 * gate_width, or the generator’s own when it provideshalf_size). NaN-padded pastcount[e].- Type:
wp.array
- left¶
Flat
[E * max_gates]vec3fleft gate endpoints (position + half_size * left_axis). NaN-padded pastcount[e].- Type:
wp.array
- right¶
Flat
[E * max_gates]vec3fright gate endpoints (position - half_size * left_axis). NaN-padded pastcount[e].- Type:
wp.array
- valid¶
[E]int32environment validity flags (0 or 1). Convert to a boolean tensor viawp.to_torch(...).bool().- Type:
wp.array
- count¶
[E]int32real gate counts per env. All other arrays are NaN-padded for slotsi >= count[e].- Type:
wp.array
- generation¶
[E]int32: the seed epoch (GateGenerator.seeds.epoch) each env’s current gates were built at.0until the first advance. It is the epoch, not a change counter: a reseed at the same epoch (rng.set_seeds_warp,Course.generate(seeds=...)) does not change it, and afterseeds.reset_epoch()the same values come back. Only while epochs are advanced and nothing reseeds or resets them does it change exactly when an env gets a NEW sequence (generate(advance=True, ...)/Course.regenerate(advance=True, ...)), so that comparing it on device to a stored copy detects every regeneration.GateGeneratoralways allocates it;Noneon aGateSequencebuilt elsewhere.- Type:
wp.array or None
- fail_mask¶
[E]int32per-env fail bitmask: bitiset means checkifailed (fail_bitsnames the bits:validity.gate_default’s 0-5 arecount,finite,tangent,spacing,crossing,grade; plugin checks own 16-30). When it is notNone,valid[e] == (fail_mask[e] == 0).GateGeneratorandwarp_gate.alloc_gate_sequencealways allocate it (finalize_gate_sequencewrites it);Noneon aGateSequencebuilt by hand.- Type:
wp.array or None
- fail_bits¶
name -> bit indexof every bit offail_maskthe pipeline assigns (GateGenerator.program.fail_bits); the crossing / grade bits are named even when their check is off (then never set). Empty on aGateSequencebuilt elsewhere.
- attributes¶
The per-gate attributes the pipeline exports, keyed by the channel name without its domain prefix (
anchors.acme.tag/gates.acme.tag->"acme.tag"): flat[E * max_gates]arrays, NaN (floats) /-1(int32) pastcount[e]. Best effort: an attribute with no path to the gate slots (a non-raworder, a plugin stations stage, a channel a stage writes on the centerline, e.g. an elevation withelevation_on="centerline") is left out (GateGenerator.program.attributeslists what is there). Empty unless a stage exports one.- Type:
Mapping[str, wp.array]
- layout¶
The batch’s
Layout(stride=max_gates), set on everyGateSequenceTrackGen makes (a generator’s result, aview(),clone(),alloc());Noneon one built by hand (validate()infers it).- Type:
Layout or None
- validate(need=())¶
Check every field of this result against its layout; return the layout.
The layout is
layoutwhen set, else inferred (num_envsfromcount,stridefrom the first per-point field, the device ofcount,closed=True; nothing is mutated). Then every array field that is notNonemust be a contiguous 1-D array of its dtype,[E * stride](per point) or[E](per env), on the layout’s device (compared canonically:"cuda"=="cuda:0"), and everyattributesentry a contiguous[E * stride]float32 / int32 / vec2f / vec3f array on that device. Host only (a few microseconds): no device work, safe inside a capture.- Parameters:
need – Field names that must not be
None(an optional field a consumer reads).- Returns:
The stored or inferred
Layout.- Raises:
ValueError – the first field that does not match, naming it and the expected shape (e.g.
Track.inner: expected a contiguous [3072] vec3f ([E*stride] = [8*384]) array on cpu, got shape (3064,) vec3f on cpu); a field ofneedthat isNone; acountthat is not an array.
- Return type:
- view(e0, e1)¶
A zero-copy view of envs
[e0, e1)of this result.Every array is a slice of this result’s array (per point
[e0 * stride : e1 * stride], per env[e0 : e1]): the same memory, read and written in place, and kept alive by the view.Nonefields stayNone;attributesare sliced alike;fail_bitsis shared;layoutisLayout(e1 - e0, stride, device, closed). A view is a result like any other: every TrackGen kernel indexes it from its own element 0, so it can be generated into (TrackGenerator(..., out= big.view(0, 4)): mixed batches), consumed by the utilities, copied, cloned and viewed again. No device work and no allocation: callable inside a capture.- Raises:
IndexError – unless
0 <= e0 < e1 <= num_envs.TypeError – non-integer indices.
ValueError – this result does not validate (
validate()).
- Parameters:
- copy_from(src, *, stream=None, ctx=None)¶
Copy every field this result holds from
src(same class, same layout).One stream-ordered device copy per held field (a field
Nonehere is skipped) and perattributeskey of this result (srcmay hold more keys). No allocation and no host sync, so it is the hot-path form of a snapshot (copy into a preallocatedalloc()result) and it records into a caller’s capture (memcpy nodes). Host metadata (fail_bits,layout) is not copied.t.copy_from(t)is a no-op.The copies run on
ctx, elsestream=> an ambientLaunchContext.scope> the stream that producedsrc(the generator’s constructorstream=) > an enclosing torch capture > Warp’s current stream.copy_fromonly knows the producer’s DEFAULT stream: pass the stream you generated on (or order the streams with events) when a generation ran elsewhere.- Parameters:
src – A result of the same class (
Track/GateSequence/Centerline).stream – Optional
wp.Stream(or"torch").ctx – Optional
LaunchContext(not withstream=).
- Raises:
TypeError –
srcis not of this result class;stream=andctx=together.ValueError – either side does not validate; the layouts differ (canonical device); a field held here is
Noneinsrc; an attribute key here is missing fromsrcor has another dtype; a partial overlap of a field with its source.
- Return type:
None
- clone(*, stream=None)¶
A fully-owned deep copy (new memory for every held field and attribute).
COLD: allocates and blocks every call (use
copy_from()into a preallocatedalloc()result on a hot path). Allocated and copied on Warp’s CURRENT stream (wherewp.emptyallocates), then a host wait on that stream: the clone is complete when it returns, so it is safe to read or write on ANY stream right away (.numpy(), a utility,copy_fromon a generator’s stream). When the result was produced on another stream (stream=, else an ambient scope, else the generator’s constructorstream=), Warp’s current stream first waits on it.Nonefields stayNone,attributesare copied,fail_bitsis shared (an immutable mapping),layoutis set; the class (a subclass) is kept.- Parameters:
stream – The stream that PRODUCED this result (
wp.Streamor"torch"), e.g.track = gen.generate(stream=s, sync=False); snap = track.clone(stream=s).- Raises:
track_gen.exec.CaptureError – inside any capture (Warp CPU / CUDA or torch), before allocating; inside a graph,
copy_frominto a preallocatedalloc()result instead.ValueError – this result does not validate (a malformed hand-built result).
- classmethod alloc(layout, *, attributes=None)¶
A result with every field allocated, in the “no track yet” state.
Per-point fields (and attributes) hold their padding (NaN;
-1for int32),count/valid/truncated/generation/fail_maskare 0,length/winding0;layoutislayoutwith the canonical device;fail_bitsis empty. Allocation and fills run on Warp’s CURRENT stream (likewp.full), then a host wait on it: the result is complete when it returns, so it can be read or written on ANY stream right away (snap.copy_from(track)on a generator’s stream,TrackGenerator(..., out=big.view(0, 4), stream=s)). COLD: allocates and blocks.- Parameters:
- Raises:
TypeError –
layoutis not aLayout; an attribute dtype outside the four;attributeson aCenterline.ValueError – an attribute key that is not
"<package>.<name>".track_gen.exec.CaptureError – inside a capture (before allocating).
fail_maskandfail_bitssay why an env is invalid: the bit table isGATE_FAIL_BITSplus the pipeline’s plugin checks (see Gate fail bits).fail_maskisNoneon aGateSequencebuilt elsewhere; when it is set,valid[e] == (fail_mask[e] == 0).attributesholds the per-gate attributes the pipeline exports (see Gate plugin channels).- __init__(position, tangent, forward, orientation, half_size, left, right, valid, count, generation=None, fail_mask=None, fail_bits=<factory>, attributes=<factory>, layout=None)¶
- Parameters:
- Return type:
None
- classmethod __new__(*args, **kwargs)¶
- class Centerline[source]¶
Bases:
objectA batched closed 3D centerline without a road band.
What a gates-mode
Coursethreads through its gates (course.course_line.centerline; the course line is internal toCoursein 0.x): the members a centerline consumer reads (HasCenterline:TrackLocalizer,localize.curvature/speed_profile), with the same flat storage as aTrack: per-point arrays[E * stride](NaN pastcount[e]), per-env arrays[E].- center¶
[E * stride]vec3fcenterline points.- Type:
warp._src.types.array
- tangent¶
[E * stride]vec3funit tangents.- Type:
warp._src.types.array
- arclen¶
[E * stride]float32cumulative arc length.- Type:
warp._src.types.array
- length¶
[E]float32loop length.- Type:
warp._src.types.array
- count¶
[E]int32real point counts.- Type:
warp._src.types.array
- valid¶
[E]int32validity flags (0 / 1).- Type:
warp._src.types.array
- generation¶
[E]int32generation epoch, orNone.- Type:
warp._src.types.array | None
- layout¶
Its
Layout(Noneon one built by hand:validate()infers it).- Type:
track_gen._src.types.Layout | None
- validate(need=())¶
Check every field of this result against its layout; return the layout.
The layout is
layoutwhen set, else inferred (num_envsfromcount,stridefrom the first per-point field, the device ofcount,closed=True; nothing is mutated). Then every array field that is notNonemust be a contiguous 1-D array of its dtype,[E * stride](per point) or[E](per env), on the layout’s device (compared canonically:"cuda"=="cuda:0"), and everyattributesentry a contiguous[E * stride]float32 / int32 / vec2f / vec3f array on that device. Host only (a few microseconds): no device work, safe inside a capture.- Parameters:
need – Field names that must not be
None(an optional field a consumer reads).- Returns:
The stored or inferred
Layout.- Raises:
ValueError – the first field that does not match, naming it and the expected shape (e.g.
Track.inner: expected a contiguous [3072] vec3f ([E*stride] = [8*384]) array on cpu, got shape (3064,) vec3f on cpu); a field ofneedthat isNone; acountthat is not an array.
- Return type:
- view(e0, e1)¶
A zero-copy view of envs
[e0, e1)of this result.Every array is a slice of this result’s array (per point
[e0 * stride : e1 * stride], per env[e0 : e1]): the same memory, read and written in place, and kept alive by the view.Nonefields stayNone;attributesare sliced alike;fail_bitsis shared;layoutisLayout(e1 - e0, stride, device, closed). A view is a result like any other: every TrackGen kernel indexes it from its own element 0, so it can be generated into (TrackGenerator(..., out= big.view(0, 4)): mixed batches), consumed by the utilities, copied, cloned and viewed again. No device work and no allocation: callable inside a capture.- Raises:
IndexError – unless
0 <= e0 < e1 <= num_envs.TypeError – non-integer indices.
ValueError – this result does not validate (
validate()).
- Parameters:
- copy_from(src, *, stream=None, ctx=None)¶
Copy every field this result holds from
src(same class, same layout).One stream-ordered device copy per held field (a field
Nonehere is skipped) and perattributeskey of this result (srcmay hold more keys). No allocation and no host sync, so it is the hot-path form of a snapshot (copy into a preallocatedalloc()result) and it records into a caller’s capture (memcpy nodes). Host metadata (fail_bits,layout) is not copied.t.copy_from(t)is a no-op.The copies run on
ctx, elsestream=> an ambientLaunchContext.scope> the stream that producedsrc(the generator’s constructorstream=) > an enclosing torch capture > Warp’s current stream.copy_fromonly knows the producer’s DEFAULT stream: pass the stream you generated on (or order the streams with events) when a generation ran elsewhere.- Parameters:
src – A result of the same class (
Track/GateSequence/Centerline).stream – Optional
wp.Stream(or"torch").ctx – Optional
LaunchContext(not withstream=).
- Raises:
TypeError –
srcis not of this result class;stream=andctx=together.ValueError – either side does not validate; the layouts differ (canonical device); a field held here is
Noneinsrc; an attribute key here is missing fromsrcor has another dtype; a partial overlap of a field with its source.
- Return type:
None
- clone(*, stream=None)¶
A fully-owned deep copy (new memory for every held field and attribute).
COLD: allocates and blocks every call (use
copy_from()into a preallocatedalloc()result on a hot path). Allocated and copied on Warp’s CURRENT stream (wherewp.emptyallocates), then a host wait on that stream: the clone is complete when it returns, so it is safe to read or write on ANY stream right away (.numpy(), a utility,copy_fromon a generator’s stream). When the result was produced on another stream (stream=, else an ambient scope, else the generator’s constructorstream=), Warp’s current stream first waits on it.Nonefields stayNone,attributesare copied,fail_bitsis shared (an immutable mapping),layoutis set; the class (a subclass) is kept.- Parameters:
stream – The stream that PRODUCED this result (
wp.Streamor"torch"), e.g.track = gen.generate(stream=s, sync=False); snap = track.clone(stream=s).- Raises:
track_gen.exec.CaptureError – inside any capture (Warp CPU / CUDA or torch), before allocating; inside a graph,
copy_frominto a preallocatedalloc()result instead.ValueError – this result does not validate (a malformed hand-built result).
- classmethod alloc(layout, *, attributes=None)¶
A result with every field allocated, in the “no track yet” state.
Per-point fields (and attributes) hold their padding (NaN;
-1for int32),count/valid/truncated/generation/fail_maskare 0,length/winding0;layoutislayoutwith the canonical device;fail_bitsis empty. Allocation and fills run on Warp’s CURRENT stream (likewp.full), then a host wait on it: the result is complete when it returns, so it can be read or written on ANY stream right away (snap.copy_from(track)on a generator’s stream,TrackGenerator(..., out=big.view(0, 4), stream=s)). COLD: allocates and blocks.- Parameters:
- Raises:
TypeError –
layoutis not aLayout; an attribute dtype outside the four;attributeson aCenterline.ValueError – an attribute key that is not
"<package>.<name>".track_gen.exec.CaptureError – inside a capture (before allocating).
- __init__(center, tangent, arclen, length, count, valid, generation=None, layout=None)¶
- Parameters:
center (array)
tangent (array)
arclen (array)
length (array)
count (array)
valid (array)
generation (array | None)
layout (Layout | None)
- Return type:
None
- classmethod __new__(*args, **kwargs)¶
Capability protocols¶
What each runtime utility reads from its source (Capability protocols). A shipped protocol never changes: a new capability is a new protocol.
- class HasCenterline[source]¶
Bases:
ProtocolA batched closed centerline: what
TrackLocalizerandlocalize.curvature/speed_profileread.TrackandCenterlinesatisfy it.- __init__(*args, **kwargs)¶
- classmethod __new__(*args, **kwargs)¶
- class HasBand[source]¶
Bases:
ProtocolA centerline with its road band: what
CollisionChecker,PropSampler,CheckpointSamplerandHeightFieldBakerread.Tracksatisfies it.- __init__(*args, **kwargs)¶
- classmethod __new__(*args, **kwargs)¶
- class HasGates[source]¶
Bases:
ProtocolGate positions: what a gates-mode
Course’s course line reads.GateSequencesatisfies it.- __init__(*args, **kwargs)¶
- classmethod __new__(*args, **kwargs)¶
- class HasGateFrames[source]¶
-
Posed gates: what a gates-mode
Course’s frame checker andCheckpointSet.from_gatesread.GateSequencesatisfies it.- __init__(*args, **kwargs)¶
- classmethod __new__(*args, **kwargs)¶
- class HasGeneration[source]¶
Bases:
ProtocolThe per-env generation epoch (
[E]int32): aTrack/GateSequence/Centerlinewhosegenerationis set. Per env only, so check it together with the protocol that gives the stride:check_source(obj, (HasCenterline, HasGeneration), consumer=...).- __init__(*args, **kwargs)¶
- classmethod __new__(*args, **kwargs)¶
- class HasValidity[source]¶
Bases:
ProtocolThe per-env validity flags (
[E]int32, 1 = valid): aTrack/GateSequence/Centerline/CheckpointSetwhosevalidis set. Per env only, so check it together with the protocol that gives the stride:check_source(obj, (HasCenterline, HasValidity), optional=("valid",), ...).- __init__(*args, **kwargs)¶
- classmethod __new__(*args, **kwargs)¶
- class HasCheckpoints[source]¶
Bases:
ProtocolAn ordered per-env checkpoint set: what
ProgressTrackerreads.CheckpointSetsatisfies it (CheckpointSampler’s set, orCheckpointSet.from_gatesof aGateSequence).- __init__(*args, **kwargs)¶
- classmethod __new__(*args, **kwargs)¶
- check_source(obj, protocol, *, consumer, topology='closed', members=None, optional=())[source]¶
Check that
objholds what a consumer reads; return itsLayout.The members of
protocol(or the narrowermembers) are read withgetattr(a__getattr__proxy works;obj.validateis never called): a missing (orNone) member raisesTypeError.protocolmay be a tuple of protocols ((HasCenterline, HasGeneration)): their members are checked together, against one layout. The layout isobj.layoutwhen it is aLayout(on aTrack/GateSequence/Centerlineit must be one, orNone; another object’s unrelatedlayoutattribute is ignored), else inferred from the checked members only:num_envsfromcount(else the first per-env member),stridefrom the first per-point member (1, i.e. undefined, when the checked members are all per env, e.g.HasGenerationalone), the device of the member that gavenum_envs,closed=True. Only those members are checked (their dtype and per-point / per-env length come from the result schemas:centeris[E * stride]vec3f,count[E]int32, …), as flat 1-D arrays on the layout’s device, contiguous; fields outside them are never looked at. Host only.- Parameters:
obj – The source (a
Track,GateSequence,Centerline, or any object with the members).protocol – The capability protocol (
HasCenterline,HasBand, …), or a tuple of them.consumer (str) – The consumer’s name, prefixed to every message (
"CollisionChecker").topology (str) – The consumer’s topology:
"closed"refuses a source whose layout hasclosed=False;"any"accepts both.members (tuple[str, ...] | None) – The members the consumer reads when it is a subset of the protocol’s.
optional – Members of
protocolread only when present: each one the source has (notNone) is checked like a required member (same messages), a missing one is skipped (valid/generation: a consumer then falls back to “every env valid” / “no self-reset”).
- Returns:
The source’s
Layout(canonical device).- Raises:
TypeError –
protocolis not a capability protocol (or a tuple of them); a missing member (naming the protocol, its members and the missing ones); a TrackGen result whoselayoutis neither aLayoutnorNone.ValueError –
members(oroptional) that are not members ofprotocol; a member that does not match (CollisionChecker: Track.inner: expected a contiguous [3072] vec3f ([E*stride] = [8*384]) array on cpu, got shape (3064,) vec3f on cpu); aclosed=Falsesource for a closed-only consumer.
- Return type: