|
Mujoco KDL Wrapper
0.5.1
MuJoCo + KDL bridge for robot kinematics and dynamics
|
Full reference for building and installing mj_kdl_wrapper without ROS, as a plain CMake C++ library and/or a Python package. For ROS 2 / colcon, see the ROS 2 Installation Guide.
Instructions target Ubuntu/Debian. CMake checks mjVERSION_HEADER and stops if MJ_KDL_MUJOCO_DIR points at an unsupported MuJoCo release.
| Dependency | Version / source | Notes |
|---|---|---|
| MuJoCo | 3.14.0 from cmake/Versions.cmake | Native library and pinned mujoco Python package must match |
| Orocos KDL | secorolab fork, branch vereshchagin-driver-weighting, from mj_kdl_wrapper.repos | Built from source; system liborocos-kdl is not used |
| vcstool | any | Checks out the KDL fork (vcs import < mj_kdl_wrapper.repos) |
| CMake | >=3.16 | Required to configure the C++ build |
| C++ compiler | C++20-capable | CMAKE_CXX_STANDARD is set to 20 |
| Python | >=3.10 | Required for the Python package |
| scikit-build-core | >=0.11.2 | Python build backend |
| pybind11 | >=2.13 | Python binding build dependency |
doxygen is only needed for the docs target; python3-dev/python3-venv only for the Python package. vcstool is also on PyPI (pip install vcstool); ROS apt sources name it python3-vcstool.
A standard CMake project. The default build is self-contained: it downloads MuJoCo and builds the Orocos KDL fork that vcs import checked out; the robot models ship in assets/. No system MuJoCo or KDL is ever used.
What happens during configure/build:
The install is self-contained. Alongside libmj_kdl_wrapper.so, its headers, and the mj_kdl_wrapper CMake package config, the built Orocos KDL fork is installed into the same prefix:
The wrapper is rpath'd to $ORIGIN as a DT_RPATH, not a DT_RUNPATH, so it loads the co-installed KDL without a build tree, and an LD_LIBRARY_PATH holding a system liborocos-kdl cannot swap it out. Consumers:
A requested version matches only within its minor version: find_package(mj_kdl_wrapper 0.3) does not accept 0.4.x. The exported target carries -Wl,--disable-new-dtags, so a consumer executable gets a DT_RPATH too.
Without CMake, use pkg-config. mj_kdl_wrapper.pc requires orocos-kdl, which the bundled fork installs next to it, and carries MuJoCo's include and library paths and the rpaths (DT_RPATH) to the wrapper's and MuJoCo's library directories:
With a KDL consumed from elsewhere (MJ_KDL_OROCOS_KDL_INSTALL_DIR or MJ_KDL_OROCOS_KDL_FROM_PACKAGE), that KDL's lib/pkgconfig must be on PKG_CONFIG_PATH as well (a colcon overlay puts it there); the rpath to its library directory is in mj_kdl_wrapper.pc.
A consumer wanting MuJoCo without KDL, glfw and OpenGL links mujoco::mujoco, which the config recreates for the exact copy this wrapper was built against:
MJ_KDL_MUJOCO_DIR and MJ_KDL_MUJOCO_VERSION are set alongside it for anyone who needs the path rather than the target.
MuJoCo is intentionally not bundled into the prefix; consumers resolve it from MJ_KDL_MUJOCO_DIR (or the mujoco pip package). Set -DMJ_KDL_INSTALL_BUNDLED_KDL=OFF to keep KDL out of a shared prefix such as /usr/local, where it could shadow a distro KDL - but then the install is no longer self-contained: the library has no rpath to any KDL, so the loader takes the first liborocos-kdl it finds, possibly a system one without the fork's solvers. Configure warns. To share one KDL, prefer One shared KDL across several projects.
Each dependency has a default source, or can point at something you already have:
| To... | Set |
|---|---|
| Use an existing MuJoCo install | -DMJ_KDL_MUJOCO_DIR=/opt/mujoco-3.14.0 |
| Override the MuJoCo download URL | -DMJ_KDL_MUJOCO_URL=<url> |
| Skip the MuJoCo download | -DMJ_KDL_FETCH_MUJOCO=OFF (then set MJ_KDL_MUJOCO_DIR) |
| Build a KDL fork checkout from elsewhere | -DMJ_KDL_OROCOS_KDL_DIR=~/src/orocos_kinematics_dynamics |
| Build a different KDL branch/tag | check it out in third_party/orocos_kinematics_dynamics |
| Reuse a prebuilt KDL by prefix | -DMJ_KDL_OROCOS_KDL_INSTALL_DIR=$HOME/ws |
| Consume KDL via its CMake package | -DMJ_KDL_OROCOS_KDL_FROM_PACKAGE=ON |
| Keep bundled KDL out of the install prefix | -DMJ_KDL_INSTALL_BUNDLED_KDL=OFF |
| Choose build / install locations | cmake -B <build-dir> -DCMAKE_INSTALL_PREFIX=<prefix> |
KDL precedence when more than one is set: MJ_KDL_OROCOS_KDL_FROM_PACKAGE > MJ_KDL_OROCOS_KDL_INSTALL_DIR > the in-tree build (MJ_KDL_OROCOS_KDL_DIR).
The default build bundles a private KDL, which is correct for a single project. When several projects need KDL, build the fork once into a shared prefix and point all of them at it, so exactly one liborocos-kdl exists (no duplicate copies or rebuilds):
MJ_KDL_OROCOS_KDL_FROM_PACKAGE=ON is the equivalent when the shared KDL is on CMAKE_PREFIX_PATH as a CMake package rather than a known prefix - this is how the ROS 2 workflow shares one KDL across a colcon overlay.
pip install builds the extension and bundles the secorolab Orocos KDL fork, PyKDL and the MuJoCo plugins. MuJoCo itself is not bundled: the wheel pins mujoco==3.14.0 and loads that package's shared library. The build is isolated - it does not reuse any C++ build tree.
PyKDL is bundled inside the wheel as a top-level extension module. It imports as PyKDL but does not appear as a separate package in pip list / uv pip list.
Verify:
All optional, passed via scikit-build-core:
| To... | Add |
|---|---|
| Editable install (dev), auto-rebuild on import | uv pip install -e . --config-settings=editable.rebuild=true |
| Put the build dir outside the source tree | --config-settings=build-dir=/path/build_py/{wheel_tag} |
| Build KDL from an existing checkout | --config-settings=cmake.define.MJ_KDL_OROCOS_KDL_DIR=/path |
| Reuse a prebuilt KDL+PyKDL prefix (skip bundling) | --config-settings=cmake.define.MJ_KDL_OROCOS_KDL_INSTALL_DIR=/prefix |
The shared-KDL option needs a prefix that also ships PyKDL; a C++-only install prefix has KDL but no PyKDL, so the default (bundle) is right for standalone use.
The wheel ships the assets/ models (mj_kdl_wrapper.ASSETS_DIR) and the examples (mj_kdl_wrapper.examples), which load the models from there:
Model paths and other model sources are documented in the Python Bindings API Guide.
Open build/docs/html/index.html. The docs include the C++ headers, C++ examples, Markdown guides, Python stubs, and Python examples, and link KDL types locally via a kdl.tag generated from the KDL the wrapper uses (the docs target builds the fork first when it is the bundled one). Requires doxygen 1.9.8 or newer.
Paths / sources:
| Flag | Default | Description |
|---|---|---|
| MJ_KDL_MUJOCO_DIR | ~/.cache/mj_kdl_wrapper/mujoco-${MJ_KDL_MUJOCO_VERSION} | MuJoCo location: download destination, or an existing install to use |
| MJ_KDL_FETCH_MUJOCO | ON | Download MuJoCo into the cache when MJ_KDL_MUJOCO_DIR is not present |
| MJ_KDL_MUJOCO_URL | (release) | MuJoCo archive URL to download |
| MJ_KDL_OROCOS_KDL_DIR | third_party/orocos_kinematics_dynamics | Fork source checkout (vcs import < mj_kdl_wrapper.repos), built in place |
| MJ_KDL_OROCOS_KDL_INSTALL_DIR | (empty) | Pre-installed Orocos KDL prefix to consume (skips building and bundling the fork) |
| MJ_KDL_OROCOS_KDL_FROM_PACKAGE | OFF | Consume Orocos KDL via find_package(orocos_kdl) on CMAKE_PREFIX_PATH; skips building and bundling the fork |
Build toggles:
| Flag | Default | Description |
|---|---|---|
| BUILD_RECORDER | ON | Enable VideoRecorder (EGL + ffmpeg headless recording) |
| BUILD_EXAMPLES | ON | Build the src/examples/ex_* programs |
| BUILD_TESTS | ON | Build and register GoogleTest tests with CTest |
| BUILD_DOCS | OFF | Generate Doxygen HTML docs (cmake --build build --target docs) |
| BUILD_PYTHON_BINDINGS | OFF | Build the pybind11 extension (driven by the Python build) |
| MJ_KDL_INSTALL_CPP_PACKAGE | ON (OFF under scikit-build) | Install the C++ library, headers, CMake package config and mj_kdl_wrapper.pc |
| MJ_KDL_INSTALL_BUNDLED_KDL | ON | Install the built Orocos KDL fork into the prefix so the install is self-contained; OFF leaves the library without a path to KDL (configure warns). No effect with MJ_KDL_OROCOS_KDL_INSTALL_DIR / MJ_KDL_OROCOS_KDL_FROM_PACKAGE |
| MJ_KDL_WITH_ROS | AUTO | Build mj_kdl_wrapper::camera_ros (publishes a rendered camera as sensor_msgs/Image + CameraInfo): AUTO when rclcpp and sensor_msgs are found, ON requires them, OFF never |
| SHOW_EQUALITY_PANEL | OFF | Show the Simulate UI Equality section |
| SHOW_GROUP_PANEL | OFF | Show the Simulate UI Group enable section |