Model — World, Craft, Coupling¶
The declarative layer: build a World, populate it with Crafts and
Couplings, then hand it to a transform.
World¶
manta.World ¶
Top-level simulation container.
Source code in manta/world.py
snapshot ¶
Return an independently resolved snapshot of this authoring model.
Deferred registrations and hooks run on a deep copy. If resolution fails, the authoring World remains untouched. Transforms call this automatically and retain the resulting fixed model revision.
Source code in manta/world.py
add_field ¶
Register a Field with this world. One instance per Field
subclass is allowed — call field.add(disturbance) on the
registered instance to attach more sources.
Returns self for chaining.
Source code in manta/world.py
get_field ¶
get_or_create_field ¶
Return the registered field of type cls, creating + adding
a fresh empty instance if none is registered. Used by
Planet.register_disturbances so a planet's contributions land
on the same field instance whether or not the user pre-added
one.
Source code in manta/world.py
add_planet ¶
Register a planet with this world. The planet's
register_disturbances(world) is called at Sim(world)
time, attaching its standing contributions to the world's
shared fields. Multi-planet worlds superpose contributions
from every registered planet.
Source code in manta/world.py
add_craft ¶
add_craft(craft, *, position=(0.0, 0.0, 0.0), orientation=(1.0, 0.0, 0.0, 0.0), velocity=(0.0, 0.0, 0.0), angular_velocity=(0.0, 0.0, 0.0), planet=None, **extra_state)
Add a craft to the world.
Args:
craft — the Craft instance.
position — craft-origin position, WorldFrame (m).
orientation — wxyz quaternion, world-from-craft.
velocity — craft-origin velocity, WorldFrame (m/s).
angular_velocity — body rates in CraftFrame (rad/s) — the
same convention as the integrated state
(what a strapped-down gyro reads). For a
non-identity orientation, world-frame
rates must be rotated into the body first.
planet — optional exact Planet whose body-fixed
Cartesian frame this craft uses. The binding is
compile-time context for planet-dependent parts;
it does not select physical field contributions.
**extra_state — per-part state overrides
(e.g., **{"wheel.angle": 0.5}).
Source code in manta/world.py
fields_for_craft ¶
Compile-time fields scoped to exactly craft.
Physical fields remain world-scoped. This narrow overlay currently
carries only PlanetBindingField and exists so two craft in one
world can resolve different planets without a context-wide
PlanetFrame.
Source code in manta/world.py
add_coupling ¶
Add an inter-craft coupling. Both endpoint crafts must already
be registered via add_craft. The coupling forces them into the
same connected component at compile time → one shared compiled
tick over both.
Source code in manta/world.py
manta.ModelArtifact
dataclass
¶
ModelArtifact(name, model_id, artifact_id, state_spec, input_names, sensor_names, parameter_names, validation, _world, _authoring_world, derivation=(lambda: MappingProxyType({}))())
One resolved World revision shared by all artifacts of a transform.
The authoring World is never frozen. Constructing another transform from
it captures a new revision, so users may add or remove parts between a
Sim, EKF, UKF, or controller build. _world is the transform-owned
snapshot and is intentionally not an authoring surface.
validation_id
property
¶
Identity of the structural validation receipt for this model.
with_derivation ¶
Return this physical model with immutable provenance attached.
Source code in manta/model.py
transform_metadata ¶
Canonical provenance every model-derived Module must carry.
Source code in manta/model.py
with_derivations ¶
Carry provenance forward onto a newly derived physical model.
Source code in manta/model.py
manta.ModelValidationReport
dataclass
¶
Certificate of structural checks completed before using a model.
Validation failures raise before this report is constructed; valid is
consequently always true. This is not a container for failed validation.
Craft¶
manta.Craft ¶
A collection of parts with shared rigid-body dynamics.
Internally a craft is a tree of parts rooted at Craft.root (a
RootPart). craft.add(part) is sugar for craft.root.add(part);
craft.parts returns a flat tuple of all parts in the tree (DFS
order). Nested composition (e.g. a joint hosting another joint
for a pan-tilt gimbal) is supported via the standard composite
add() chain on individual parts.
State (13 DOF):
position : Vec3[WorldFrame]
orientation : Quat[WorldFrame, CraftFrame]
velocity : Vec3[WorldFrame]
angular_velocity : Vec3[CraftFrame]
plus one Scalar per R1 State slot declared on any of the parts.
Source code in manta/craft.py
parts
property
¶
Flat tuple of every part in the tree, root first (DFS order). Excludes the root itself.
total_mass
property
¶
Sum of the declared mass of every genuinely inertial part
(contributes_inertia trait) — gain-like mass parameters
(e.g. TrajectoryEndpoint's feedforward) don't count.
add ¶
remove ¶
Detach a part anywhere in this craft's tree.
Existing transforms retain their private model revision. A later transform captures the edited tree.
Source code in manta/craft.py
aggregate_inertials ¶
Public-facing accessor: see _aggregate_inertials. Useful for
external inspection and tests.
sample_noise ¶
Draw one tick of white-Gaussian samples for every declared
Noise slot on every part. Returns a dict of
"<part>.<noise>" → np.ndarray ready to merge into the state
dict before calling the compiled tick.
This is the model-side draw, keyed by full state name. The
running sim does not call it — NumpySim drives noise through
the Module's NOISE port with a NoiseDriver. Keep it for
hand-driven ticks and for tests that want the per-channel
sigmas without a backend.
Slots whose sigma is 0 return zero vectors without consuming RNG state (so a deterministic-seed sim stays reproducible regardless of which noise channels are active).
Source code in manta/craft.py
initial_state ¶
Build the initial state dict for the compiled tick.
Returns a dict with the rigid-body slots (position, orientation,
velocity, angular_velocity) AND a "<part_name>.<state_name>"
entry for every part that declares state. Defaults come from each
State declaration's init; keyword overrides replace them by name.
Source code in manta/craft.py
Coupling¶
A Coupling joins two crafts with a force exchanged between them — as
opposed to an articulation (a 1-DOF joint inside one craft). For when to
reach for which, see
Articulation vs coupling.
manta.Coupling ¶
Bases: ABC
Abstract base for inter-craft constraints.
A concrete subclass (e.g. Tether) declares two craft endpoints
(craft_a / craft_b) and produces the extra wrench terms they
exchange (compute_wrenches_sym) in the tick graph for the connected
component. The presence of a Coupling forces both crafts into the same
compile unit.
Source code in manta/couplings/base.py
compute_wrenches_sym
abstractmethod
¶
The wrench pair (wrench_on_a, wrench_on_b) this coupling
applies, given each craft's TickContext. Frames: each wrench is
in its own craft's CraftFrame, at that craft's origin.
Source code in manta/couplings/base.py
manta.couplings.Tether ¶
Tether(craft_a, endpoint_a, craft_b, endpoint_b, *, name=None, stiffness, damping=0.0, rest_length=0.0, slack_smoothing=0.001)
Bases: Coupling
Slack-capable spring-damper tether between two TetherEndpoint Parts.
Args: craft_a, craft_b — the two coupled crafts (Craft instances). endpoint_a, endpoint_b — names of the TetherEndpoint Parts on craft_a / craft_b (strings). stiffness — spring constant k, N/m (taut only). damping — damper constant c, N·s/m (taut only). rest_length — natural length L_rest, m. Slack below, taut above. slack_smoothing — half-width, m, of the C¹ blend band around the taut/slack boundary (and, scaled by k, of the tension-only clamp). 0 ⇒ hard switches.
Convention: tension only. When L > rest_length the tether pulls A toward B (and B toward A), the damper resisting length rate; the net force is clamped so it can never push. When L < rest_length the tether is slack and exerts exactly zero force — the crafts move freely until the rope tautens again.
Source code in manta/couplings/tether.py
compute_wrenches_sym ¶
Return (wrench_on_a_at_craft_origin, wrench_on_b_at_craft_origin).
Both wrenches are in their respective CraftFrame, lifted to the body origin (force-at-offset + lever-arm torque). The compile layer adds these directly to each craft's aggregate net wrench.
Source code in manta/couplings/tether.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | |