Skip to content

Load extra MuJoCo plugins using a simulate shim - #12

Open
scastro-nasa wants to merge 1 commit into
pal-robotics:masterfrom
NASA-JSC-Robotics:simulate-load-plugins
Open

Load extra MuJoCo plugins using a simulate shim#12
scastro-nasa wants to merge 1 commit into
pal-robotics:masterfrom
NASA-JSC-Robotics:simulate-load-plugins

Conversation

@scastro-nasa

@scastro-nasa scastro-nasa commented Jul 7, 2026

Copy link
Copy Markdown

This PR removes the need of having to copy built MuJoCo extensions / plugins to the same folder as MuJoCo just so that simulate works with new plugins. See the discussions in ros-controls/mujoco_ros2_control#205

This is done by replacing the direct symlink to simulate with a shim script that modifies LD_PRELOAD and finds registered plugins via ament resources before launching the MuJoCo simulate app.

One open question: This means we still need this shim to be built in RoboStack, so we'll have to modify the patch that @traversaro applied if we go down this path.

@scastro-nasa
scastro-nasa force-pushed the simulate-load-plugins branch from dfd3e68 to e282171 Compare July 7, 2026 17:38
Comment thread src/plugin_path_shim.cc
Comment on lines +22 to +75
// Load all .so plugins from a directory, following symlinks.
void loadPluginsFromDirectory(const std::string& plugin_dir) {
std::error_code ec;
if (!std::filesystem::is_directory(plugin_dir, ec)) {
return;
}

for (const auto& entry : std::filesystem::directory_iterator(plugin_dir, ec)) {
if (!entry.is_regular_file(ec)) {
continue;
}

const auto& path = entry.path();
if (path.extension() != ".so") {
continue;
}

int before = mjp_pluginCount();
mj_loadPluginLibrary(path.c_str());
int after = mjp_pluginCount();
if (after > before) {
std::printf("Plugins registered by library '%s':\n", path.filename().c_str());
for (int i = before; i < after; ++i) {
std::printf(" %s\n", mjp_getPluginAtSlot(i)->name);
}
} else {
std::printf("No plugins loaded from: '%s':\n", path.filename().c_str());
}
}
}

__attribute__((constructor))
void loadAmentResourcePlugins() {
std::printf("Loading plugins from ament resources...\n");

try {
// Try to find all packages that registered mujoco plugins via the ament resource index
auto plugins = ament_index_cpp::get_resources("mujoco_plugins");
for (const auto& [package_name, _] : plugins) {
std::string content;
std::string prefix;
if (ament_index_cpp::get_resource("mujoco_plugins", package_name, content, &prefix)) {
const std::string plugin_dir = prefix + "/" + content;
std::printf("Loading MuJoCo plugins from package '%s': %s\n", package_name.c_str(),
plugin_dir.c_str());
loadPluginsFromDirectory(plugin_dir);
}
}
} catch (const std::exception& e) {
std::fprintf(stderr, "mujoco_plugin_shim: skipping ament plugin discovery: %s\n", e.what());
}

std::printf("Finished loading plugins from ament resources!\n");
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think this stuff should stay here as-is, or worth making a portable library that we can reuse in mujoco_ros2_control instead of copy pasting?

@traversaro

Copy link
Copy Markdown
Contributor

Instead of shimming simulate, perhaps it may be cleaner to just define a custom executable using the libsimulate library in mujoco-ros2-control with any custom logic required by the context?

@scastro-nasa

scastro-nasa commented Jul 7, 2026

Copy link
Copy Markdown
Author

Instead of shimming simulate, perhaps it may be cleaner to just define a custom executable using the libsimulate library in mujoco-ros2-control with any custom logic required by the context?

That was my initial idea too, but there were concerns about copy-pasting too much code (basically 550 LOC + having to keep up with updates)... but I'm all for that approach instead :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants