Skip to main content

mujoco_rs/
lib.rs

1//! # MuJoCo-rs
2//! A wrapper around the MuJoCo C library with a Rust-native viewer.
3//! If you're familiar with MuJoCo, this should be pretty straightforward to use as the wrappers
4//! mainly encapsulate some C structs or just rename them to match Rust's PascalCase style.
5//!
6//! The main structs are [`wrappers::mj_model::MjModel`] and [`wrappers::mj_data::MjData`].
7//! These two structs (and some others) wrap the C structure in order to achieve memory safety.
8//!
9//! Their fields aren't publicly exposed and can instead be manipulated through views
10//! (e.g., [`MjData::joint`](wrappers::mj_data::MjData::joint) and then [`wrappers::mj_data::MjJointDataInfo::view`]).
11//! To access the wrapped attributes directly, call the corresponding `ffi()` methods
12//! (e.g., [`MjData::ffi`](wrappers::MjData::ffi)).
13//!
14//! ## MuJoCo version
15//!
16//! MuJoCo-rs relies on MuJoCo [3.9.0](https://github.com/google-deepmind/mujoco/releases/tag/3.9.0).
17//!
18//! ## Documentation
19//! A more guided documentation can be obtained [here](https://mujoco-rs.readthedocs.io/en/v5.0.x/).
20//!
21//! ### Missing library errors
22//! Guided documentation also contains information on how to **configure MuJoCo**.
23//! MuJoCo-rs cannot fully configure it itself due to MuJoCo being a shared C library. As a result, you may encounter
24//! **load-time errors** about **missing libraries**.
25//!
26//! Information on how to configure MuJoCo and resolve these issues is available
27//! [here](https://mujoco-rs.readthedocs.io/en/v5.0.x/installation.html#mujoco).
28//!
29//! ## 3D viewer
30//! The Rust-native viewer is available ([`viewer::MjViewer`]) when the `viewer` / `viewer-ui` feature is enabled,
31//! as well as MuJoCo's C++ one ([`crate::cpp_viewer::MjViewerCpp`]).
32//! The C++ viewer, however, requires manual compilation of a patched MuJoCo repository,
33//! like described [here](https://mujoco-rs.readthedocs.io/en/v5.0.x/installation.html#static-linking).
34//!
35//! ## Model editing
36//! [`MjModel`](wrappers::MjModel) can be procedurally generated through the model editing module.
37//! The specification representing the model is [`wrappers::mj_editing::MjSpec`].
38//!
39//! ## Functions
40//! Most functions are wrapped under methods at different structs. Some functions
41//! are available under the [`wrappers::fun`] module.
42//!
43//! If a certain function can't be found, you can use the raw FFI bindings, available under
44//! the [`mujoco_c`] module. Note that to access the lower-level ffi structs inside wrappers,
45//! `ffi()` or `ffi_mut()` must be called (e.g., [`MjData::ffi`](wrappers::MjData::ffi) and [`MjModel::ffi`](wrappers::MjModel::ffi)).
46//!
47//! # Cargo features
48//! This crate has the following public features:
49//! - `viewer`: enables the Rust-native MuJoCo viewer.
50//!
51//!   - `viewer-ui`: enables the (additional) user UI within the viewer.
52//!     This also allows users to add custom [`egui`](https://docs.rs/egui/0.33/egui/) widgets to the viewer.
53//!
54//! - `cpp-viewer`: enables the Rust wrapper around the C++ MuJoCo viewer.
55//!   This requires static linking to a modified fork of MuJoCo, as described in [installation](https://mujoco-rs.readthedocs.io/en/v5.0.x/installation.html#static-linking).
56//! - `renderer`: enables offscreen rendering for writing RGB and
57//!   depth data to memory or file.
58//!
59//!   - `renderer-winit-fallback`: enables the invisible window fallback (based on winit) when offscreen
60//!     rendering fails to initialize. Note that true offscreen rendering is only available on Linux platforms
61//!     when the video driver supports it. On Windows and macOS, this feature must always be
62//!     enabled when the `renderer` feature is enabled.
63//!
64//! - `auto-download-mujoco`: MuJoCo dependency will be automatically downloaded to the specified path.
65//!
66//!   - This is only available on Linux and Windows.
67//!   - The environment variable `MUJOCO_DOWNLOAD_DIR` must be set to the absolute path of the download location.
68//!   - Downloaded MuJoCo library is still a shared library. See
69//!     [installation](https://mujoco-rs.readthedocs.io/en/v5.0.x/installation.html#mujoco)
70//!     for information on complete configuration.
71//!
72//! By default, no optional features are enabled. Enable the features you need explicitly
73//! (e.g. `cargo add mujoco-rs --features "viewer-ui renderer-winit-fallback"` for support
74//! with the viewer and the viewer's extra UI, and the render with invisible window as a fallback).
75//!
76//! On macOS, the visualization features (`viewer` and `renderer`) do not work without
77//! patching the `glutin` dependency. See
78//! [installation](https://mujoco-rs.readthedocs.io/en/v5.0.x/installation.html#macos-glutin-patch)
79//! for instructions.
80//!
81//!
82use std::ffi::CStr;
83
84pub mod wrappers;
85pub mod prelude;
86pub mod util;
87pub mod error;
88
89
90#[cfg(feature = "renderer")]
91pub mod renderer;
92
93#[cfg(feature = "viewer")]
94pub mod viewer;
95
96#[cfg(feature = "cpp-viewer")]
97pub mod cpp_viewer;
98
99#[allow(warnings, clippy::approx_constant)]
100/// Raw MuJoCo C and C++ FFI bindings (auto-generated).
101pub mod mujoco_c;
102
103#[cfg(any(feature = "viewer", feature = "renderer-winit-fallback"))]
104mod winit_gl_base;
105
106#[cfg(any(feature = "viewer", feature = "renderer"))]
107pub mod vis_common;
108
109
110/// Returns the version string of the MuJoCo library.
111///
112/// # Panics
113/// Panics if the MuJoCo version string is not valid UTF-8.
114pub fn mujoco_version() -> &'static str {
115    let arr = unsafe { mujoco_c::mj_versionString() };
116    unsafe { CStr::from_ptr(arr).to_str().unwrap() }
117}
118
119/// Returns the version string of the MuJoCo library.
120#[deprecated(since = "3.0.0", note = "use `mujoco_version` instead")]
121pub fn get_mujoco_version() -> &'static str {
122    mujoco_version()
123}
124
125#[cfg(test)]
126mod tests {
127    use crate::mujoco_version;
128
129    #[test]
130    fn test_version() {
131        let version = mujoco_version();
132        assert!(!version.is_empty());
133    }
134
135
136    #[allow(unused)]
137    pub(crate) fn test_leaks() {
138        use super::*;
139        use wrappers::*;
140        use std::hint::black_box;
141
142        const N_ITEMS: usize = 10000;
143        const N_REPEATS: usize = 1000;
144        const EXAMPLE_MODEL: &str = "
145        <mujoco>
146        <worldbody>
147            <light ambient=\"0.2 0.2 0.2\"/>
148            <body name=\"ball\">
149                <geom name=\"sphere\" pos=\".2 .2 .2\" size=\".1\" rgba=\"0 1 0 1\"/>
150                <joint name=\"sphere\" type=\"free\"/>
151            </body>
152
153            <geom name=\"floor\" type=\"plane\" size=\"10 10 1\" euler=\"5 0 0\"/>
154
155        </worldbody>
156        </mujoco>
157        ";
158
159        for _ in 0..N_REPEATS {
160            let model = MjModel::from_xml_string(EXAMPLE_MODEL).expect("failed to load the model.");
161            for mut data in (0..N_ITEMS).map(|_| model.make_data()) {
162                data.joint("sphere").unwrap().view_mut(&mut data).qpos[0] /= 2.0;
163                data.step();
164                black_box(&data);
165            }
166        }
167    }
168}