Build a model#

An mjorbit model combines ordinary MuJoCo XML with optional <mjorbit> metadata. Use MjoModel.from_xml_path(...) when the file already describes the desired system, or edit an MjoSpec before compilation.

Edit before compiling#

from mjorbit import MjoSpec
from mjorbit.testdata import FREE_BODY_XML

spec = MjoSpec.from_xml_path(FREE_BODY_XML)
spec.mjorbit.use_j2 = False
spec.mjorbit.use_drag = False
spec.mjorbit.use_srp = False
spec.mjorbit.use_magnetic = False
model = spec.compile(mj_timestep=0.01)

This configuration retains the two-body reference orbit, differential gravity, and gravity-gradient torque (whose separate use_gravity_gradient flag defaults to True). The environment flags select additional models; they do not disable the orbital dynamics as a whole. The free-body analytical comparison uses this configuration to match its Clohessy–Wiltshire reference.

See forces and disturbances for the equations, surface configuration, default environment parameters, and model limitations.

MjoSpec.from_xml_string(xml, assets=...) accepts in-memory XML and an optional asset map. Prefer from_xml_path for files that include meshes or other XML, so relative asset paths remain resolvable by the runtime and viewer. spec.to_xml() serializes the editable specification; spec.copy() supports independent variants.

Spacecraft metadata#

spec.mjorbit manages the central body, environmental flags, surfaces, magnetic bodies, reaction wheels, magnetorquers, thrusters, and CMGs. Each element has an add_*, update_*, and remove_* operation. Static physical values belong in the corresponding *Spec dataclass; runtime commands belong in data.

For example, add a wheel to the bundled free body:

from mjorbit import ReactionWheelSpec

spec.mjorbit.add_reaction_wheel(
    ReactionWheelSpec(
        name="wheel_x",
        body_name="spacecraft",
        axis_body=[1.0, 0.0, 0.0],
        inertia=0.01,
        torque_limit=0.02,
    )
)
model = spec.compile(mj_timestep=0.01)

See the API reference for exact fields and signatures. Compilation resolves body names and validates metadata. Recompile after changing a spec; an existing model and its data retain the previously compiled configuration.

Runtime ownership#

Create each independent run with model.make_data(orbit=...). CPU data exposes live NumPy views such as qpos, qvel, ctrl, xpos, and sensordata. Use mjo_forward(model, data) after changing initial state, then advance with mjo_step(model, data). data.reset() restores the initial orbit and model state; supplying another OrbitInit also replaces the stored reset orbit.

The native model/data are owned by mjorbit. The wrappers do not expose mj_model or mj_data Python objects; use their supported fields and methods. For a custom application, keep model construction separate from the control loop so each episode can allocate or reset data without recompiling XML.