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 the 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 other) 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.3.7](https://github.com/google-deepmind/mujoco/releases/tag/3.3.7).
17//! 
18//! ## Documentation
19//! A more guided documentation can be obtained [here](https://mujoco-rs.readthedocs.io/en/latest/).
20//! 
21//! ## 3D viewer
22//! The Rust-native viewer is available ([`viewer::MjViewer`]), as well as the MuJoCo's original C++
23//! one ([`cpp_viewer::MjViewerCpp`]).
24//! The C++ viewer however requires manual compilation of a patched MuJoCo repository,
25//! like described [here](https://mujoco-rs.readthedocs.io/en/latest/installation.html#static-linking-with-c-viewer).
26//! 
27//! ## Model editing
28//! [`MjModel`](wrappers::MjModel) can be procedurally generated through the model editing module.
29//! The specification representing the model is [`wrappers::mj_editing::MjSpec`]
30//! 
31//! ## Features
32//! This crate has the following public features:
33//! - `viewer`, which enables the Rust-native viewer ([`viewer::MjViewer`]),
34//! - `cpp-viewer`, which enables the MuJoCo's original viewer (C++ based) ([`cpp_viewer::MjViewerCpp`]),
35//! - `renderer`, which enables the image renderer ([`renderer::MjRenderer`]).
36//! 
37//! ## Functions
38//! Most functions are wrapped under methods at different structs. Some functions
39//! are available under the [`wrappers::fun`] module.
40//! 
41//! If a certain function can't be found, you can use the raw FFI bindings, available under 
42//! the [`mujoco_c`] module. Note that to access the lower-level ffi structs inside of wrappers,
43//! `ffi()` or `ffi_mut()` must be called (e.g., [`MjData::ffi`](wrappers::MjData::ffi) and [`MjModel::ffi`](wrappers::MjModel::ffi)). 
44use std::ffi::CStr;
45
46pub mod wrappers;
47pub mod prelude;
48pub mod util;
49
50
51#[cfg(feature = "renderer")]
52pub mod renderer;
53
54#[cfg(feature = "viewer")]
55pub mod viewer;
56
57#[cfg(feature = "cpp-viewer")]
58pub mod cpp_viewer;
59
60#[allow(warnings)]
61pub mod mujoco_c;  // raw MuJoCo C and C++ bindings
62
63#[cfg(any(feature = "viewer", feature = "renderer"))]
64mod render_base;
65
66
67/// Returns the version string of the MuJoCo library.
68pub fn get_mujoco_version() -> &'static str {
69    let arr = unsafe { mujoco_c::mj_versionString() };
70    unsafe { CStr::from_ptr(arr).to_str().unwrap() }
71}
72
73#[cfg(test)]
74mod tests {
75    use crate::get_mujoco_version;
76
77    #[test]
78    fn test_version() {
79        let version = get_mujoco_version();
80        assert!(!version.is_empty());
81    }
82
83
84    #[allow(unused)]
85    pub(crate) fn test_leaks() {
86        use super::*;
87        use wrappers::*;
88        use std::hint::black_box;
89
90        const N_ITEMS: usize = 10000;
91        const N_REPEATS: usize = 1000;
92        const EXAMPLE_MODEL: &str = "
93        <mujoco>
94        <worldbody>
95            <light ambient=\"0.2 0.2 0.2\"/>
96            <body name=\"ball\">
97                <geom name=\"sphere\" pos=\".2 .2 .2\" size=\".1\" rgba=\"0 1 0 1\"/>
98                <joint name=\"sphere\" type=\"free\"/>
99            </body>
100
101            <geom name=\"floor\" type=\"plane\" size=\"10 10 1\" euler=\"5 0 0\"/>
102
103        </worldbody>
104        </mujoco>
105        ";
106
107        std::hint::black_box(
108            for _ in 0..N_REPEATS {
109                let model = MjModel::from_xml_string(EXAMPLE_MODEL).expect("failed to load the model.");
110                for mut data in (0..N_ITEMS).map(|_| model.make_data()) {
111                    data.joint("sphere").unwrap().view_mut(&mut data).qpos[0] /= 2.0;
112                    data.step();
113                }
114            }
115        )
116    }
117}