Add model.xml fallback search path to mjz decoder

PiperOrigin-RevId: 949690037
Change-Id: I93978c1f9ded12c69ffe321fe1f85721db32f555
This commit is contained in:
Sam Haves
2026-07-17 12:02:03 -07:00
committed by Copybara-Service
parent e3293a5f29
commit ebd4abae03
2 changed files with 24 additions and 10 deletions
+1
View File
@@ -72,6 +72,7 @@ General
integrator and flex stiffness present; Newton and PGS are unaffected. Bending-only models pay zero per-step integrator and flex stiffness present; Newton and PGS are unaffected. Bending-only models pay zero per-step
factorization cost (the factor is precomputed in :ref:`mj_setConst<mj_setConst>`). Inverse dynamics factorization cost (the factor is precomputed in :ref:`mj_setConst<mj_setConst>`). Inverse dynamics
(:ref:`mj_inverse<mj_inverse>`) is now discrete-consistent with forward dynamics for gated models. (:ref:`mj_inverse<mj_inverse>`) is now discrete-consistent with forward dynamics for gated models.
- The ``mjz`` decoder now searches for ``model.xml`` at the root of the archive as a fallback if the archive-named XML is not found.
.. admonition:: Breaking API changes .. admonition:: Breaking API changes
:class: attention :class: attention
+23 -10
View File
@@ -87,20 +87,33 @@ class ZipArchiveProvider : public mjpResourceProvider {
files_[stat.m_filename] = FileInfo{i, size, {}}; files_[stat.m_filename] = FileInfo{i, size, {}};
} }
// Look for the root XML model in the archive. First look for an XML file // Look for the root XML model in the archive. We try the following
// with the same name as the archive itself. Failing that, look for an XML // locations:
// file within a subdirectory with the same name as the archive. // 1. [archive_name].xml at the root of the archive.
// 2. [archive_name]/[archive_name].xml inside a subdirectory.
// 3. model.xml at the root of the archive (common zipped MJCF pattern).
const std::filesystem::path path(name_); const std::filesystem::path path(name_);
root_model_ = (path / path.stem()).generic_string() + ".xml"; const std::string stem = path.stem().string();
if (!Contains(root_model_)) { std::vector<std::string> candidates = {
root_model_ = (path / stem).generic_string() + ".xml",
(path / path.stem() / path.stem()).generic_string() + ".xml"; (path / stem / stem).generic_string() + ".xml",
if (!Contains(root_model_)) { (path / "model").generic_string() + ".xml",
SetError(error, error_sz, "Zip error: no root XML file found."); };
return;
bool found = false;
for (const auto& candidate : candidates) {
if (Contains(candidate)) {
root_model_ = candidate;
found = true;
break;
} }
} }
if (!found) {
SetError(error, error_sz, "Zip error: no root XML file found.");
return;
}
// Setup mjpResourceProvider callbacks. // Setup mjpResourceProvider callbacks.
mount = [](mjResource* resource) { mount = [](mjResource* resource) {
return 0; return 0;