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//! Currently, no direct functions are provided. Some of the functions are made into methods at appropriate
7//! structs, while others can be found under ``mujoco_rs::mujoco_c`` module. Missing structs
8//! can also be obtained there.
9//! 
10//! To access the lower-level ffi structs in the wrappers, call either the ``ffi()`` method
11//! or the ``ffi_mut()`` method.
12//! 
13//! The main structs are [`wrappers::mj_model::MjModel`] and [`wrappers::mj_data::MjData`].
14//! The Rust-native viewer is available in [`viewer::MjViewer`].
15//! 
16
17use std::ffi::CStr;
18
19pub mod wrappers;
20pub mod prelude;
21pub mod util;
22
23#[cfg(feature = "viewer")]
24pub mod viewer;
25
26#[allow(warnings)]
27pub mod mujoco_c;  // raw MuJoCo C and C++ bindings
28
29
30/// Returns the version string of the MuJoCo library
31pub fn get_mujoco_version() -> &'static str {
32    let arr = unsafe { mujoco_c::mj_versionString() };
33    unsafe { CStr::from_ptr(arr).to_str().unwrap() }
34}
35
36#[cfg(test)]
37mod tests {
38    use crate::get_mujoco_version;
39
40    #[test]
41    fn test_version() {
42        let version = get_mujoco_version();
43        assert!(!version.is_empty());
44    }
45
46
47    #[allow(unused)]
48    pub(crate) fn test_leaks() {
49        use super::*;
50        use wrappers::*;
51        use std::hint::black_box;
52
53        const N_ITEMS: usize = 10000;
54        const N_REPEATS: usize = 1000;
55        const EXAMPLE_MODEL: &str = "
56        <mujoco>
57        <worldbody>
58            <light ambient=\"0.2 0.2 0.2\"/>
59            <body name=\"ball\">
60                <geom name=\"sphere\" pos=\".2 .2 .2\" size=\".1\" rgba=\"0 1 0 1\"/>
61                <joint name=\"sphere\" type=\"free\"/>
62            </body>
63
64            <geom name=\"floor\" type=\"plane\" size=\"10 10 1\" euler=\"5 0 0\"/>
65
66        </worldbody>
67        </mujoco>
68        ";
69
70        for _ in 0..N_REPEATS {
71            let model = MjModel::from_xml_string(EXAMPLE_MODEL).expect("failed to load the model.");
72            let mut datas: Vec<_> = (0..N_ITEMS).map(|_| model.make_data()).collect();
73
74            for data in datas.iter_mut() {
75                data.joint("sphere").unwrap().view_mut(data).qpos[0] /= 2.0;
76                data.step();
77            }
78        }
79    }
80}