Re-implement VFS internals in C++, removing the constraints of the previous implementation.

PiperOrigin-RevId: 649433087
Change-Id: Icaa3e6b7f2ef14f56b04fef2f4360b46d8b5f022
This commit is contained in:
Kyle Bayes
2024-07-04 09:21:18 -07:00
committed by Copybara-Service
parent 118b6810b3
commit 57e6760ec9
19 changed files with 513 additions and 717 deletions
-16
View File
@@ -409,19 +409,6 @@ class MuJoCoBindingsTest(parameterized.TestCase):
np.testing.assert_array_equal(self.model.geom_size[1], [0.5, 0.5, 0.5])
np.testing.assert_array_equal(model_copy.geom_size[1], [0.1, 0.1, 0.1])
def test_assets_array_filename_too_long(self):
# Longest allowed filename (excluding null byte)
limit = mujoco.mjMAXVFSNAME - 1
contents = b'<mujoco/>'
valid_filename = 'a' * limit
mujoco.MjModel.from_xml_path(valid_filename, {valid_filename: contents})
invalid_filename = 'a' * (limit + 1)
expected_message = (
f'Filename length 1000 exceeds 999 character limit: {invalid_filename}')
with self.assertRaisesWithLiteralMatch(ValueError, expected_message):
mujoco.MjModel.from_xml_path(invalid_filename,
{invalid_filename: contents})
def test_mjdata_can_copy(self):
self.data.qpos = [0, 0, 0.1*np.sqrt(2) - 0.001,
np.cos(np.pi/8), np.sin(np.pi/8), 0, 0, 0,
@@ -856,9 +843,6 @@ Return the current version of MuJoCo as a null-terminated string.
Euler integrator, semi-implicit in velocity.
""")
def test_int_constant(self):
self.assertEqual(mujoco.mjMAXVFSNAME, 1000)
def test_float_constant(self):
self.assertEqual(mujoco.mjMAXVAL, 1e10)
self.assertEqual(mujoco.mjMINVAL, 1e-15)
-2
View File
@@ -57,8 +57,6 @@ PYBIND11_MODULE(_constants, pymodule) {
X(mjMINIMP);
X(mjMAXIMP);
X(mjMAXCONPAIR);
X(mjMAXVFS);
X(mjMAXVFSNAME);
X(mjNEQDATA);
X(mjNDYN);
X(mjNGAIN);
+7 -15
View File
@@ -317,24 +317,22 @@ static raw::MjModel* LoadModelFileImpl(
const std::string& filename,
const std::vector<VfsAsset>& assets,
LoadFunc&& loadfunc) {
std::unique_ptr<mjVFS, void(*)(mjVFS*)> vfs(nullptr, [](mjVFS*){});
mjVFS vfs;
mjVFS* vfs_ptr = nullptr;
if (!assets.empty()) {
// mjVFS should be allocated on the heap, because it's ~2MB
vfs = decltype(vfs)(new mjVFS, [](mjVFS* vfs) {
mj_deleteVFS(vfs);
delete vfs;
});
mj_defaultVFS(vfs.get());
mj_defaultVFS(&vfs);
vfs_ptr = &vfs;
for (const auto& asset : assets) {
const int vfs_error = InterceptMjErrors(mj_addBufferVFS)(
vfs.get(), asset.name, asset.content, asset.content_size);
vfs_ptr, asset.name, asset.content, asset.content_size);
if (vfs_error) {
throw py::value_error("assets dict is too big");
}
}
}
raw::MjModel* model = loadfunc(filename.c_str(), vfs.get());
raw::MjModel* model = loadfunc(filename.c_str(), vfs_ptr);
mj_deleteVFS(vfs_ptr);
if (model && !model->buffer) {
mj_deleteModel(model);
model = nullptr;
@@ -351,12 +349,6 @@ ConvertAssetsDict(
std::vector<VfsAsset> out;
if (assets.has_value()) {
for (const auto& [name, content] : *assets) {
if (name.length() >= mjMAXVFSNAME) {
std::ostringstream error;
error << "Filename length " << name.length() << " exceeds "
<< mjMAXVFSNAME - 1 << " character limit: " << name;
throw py::value_error(error.str());
}
out.emplace_back(name.c_str(), PYBIND11_BYTES_AS_STRING(content.ptr()),
py::len(content));
}