Change mj_encode return type to 64-bit (mjtSize)
This supports encoding files larger than 2GB. PiperOrigin-RevId: 939828697 Change-Id: If60d36c61475ced20b4eb58408ffb37e25bf3db7
This commit is contained in:
committed by
Copybara-Service
parent
1e04c568e8
commit
d83ef0b6b9
@@ -2053,8 +2053,8 @@ mjfEncode
|
|||||||
|
|
||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
typedef int (*mjfEncode)(const mjSpec* s, const mjModel* m, const mjVFS* vfs,
|
typedef mjtSize (*mjfEncode)(const mjSpec* s, const mjModel* m, const mjVFS* vfs,
|
||||||
mjResource* resource);
|
mjResource* resource);
|
||||||
|
|
||||||
|
|
||||||
This callback populates the :ref:`mjResource<mjResource>` `data` member with bytes representing the
|
This callback populates the :ref:`mjResource<mjResource>` `data` member with bytes representing the
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ General
|
|||||||
- Added Nesterov momentum extrapolation with adaptive gradient restart (O'Donoghue-Candès) to the PGS solver,
|
- Added Nesterov momentum extrapolation with adaptive gradient restart (O'Donoghue-Candès) to the PGS solver,
|
||||||
significantly improving convergence. Overall PGS now requires ~2x fewer iterations.
|
significantly improving convergence. Overall PGS now requires ~2x fewer iterations.
|
||||||
|
|
||||||
|
.. admonition:: Breaking API changes
|
||||||
|
:class: attention
|
||||||
|
|
||||||
|
- Return type of :ref:`mj_encode` and the :ref:`mjfEncode` callback changed from ``int`` to ``mjtSize`` (64-bit).
|
||||||
|
|
||||||
Version 3.10.0 (June 22, 2026)
|
Version 3.10.0 (June 22, 2026)
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -3231,9 +3231,9 @@ mjSpec* mj_parseXML(const char* filename, const mjVFS* vfs, char* error, int err
|
|||||||
mjSpec* mj_parseXMLString(const char* xml, const mjVFS* vfs, char* error, int error_sz);
|
mjSpec* mj_parseXMLString(const char* xml, const mjVFS* vfs, char* error, int error_sz);
|
||||||
mjSpec* mj_parse(const char* filename, const char* content_type,
|
mjSpec* mj_parse(const char* filename, const char* content_type,
|
||||||
const mjVFS* vfs, char* error, int error_sz);
|
const mjVFS* vfs, char* error, int error_sz);
|
||||||
int mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
|
mjtSize mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
|
||||||
const char* content_type, const mjVFS* vfs, char* error,
|
const char* content_type, const mjVFS* vfs, char* error,
|
||||||
int error_sz);
|
int error_sz);
|
||||||
mjModel* mj_compile(mjSpec* s, const mjVFS* vfs);
|
mjModel* mj_compile(mjSpec* s, const mjVFS* vfs);
|
||||||
int mj_copyBack(mjSpec* s, const mjModel* m);
|
int mj_copyBack(mjSpec* s, const mjModel* m);
|
||||||
int mj_recompile(mjSpec* s, const mjVFS* vfs, mjModel* m, mjData* d);
|
int mj_recompile(mjSpec* s, const mjVFS* vfs, mjModel* m, mjData* d);
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ typedef struct mjpDecoder {
|
|||||||
|
|
||||||
//---------------------------------- Encoder -------------------------------------------------------
|
//---------------------------------- Encoder -------------------------------------------------------
|
||||||
|
|
||||||
typedef int (*mjfEncode)(const mjSpec* s, const mjModel* m, const mjVFS* vfs,
|
typedef mjtSize (*mjfEncode)(const mjSpec* s, const mjModel* m, const mjVFS* vfs,
|
||||||
mjResource* resource);
|
mjResource* resource);
|
||||||
|
|
||||||
typedef struct mjpEncoder {
|
typedef struct mjpEncoder {
|
||||||
const char* content_type;
|
const char* content_type;
|
||||||
|
|||||||
@@ -147,9 +147,9 @@ MJAPI mjSpec* mj_parse(const char* filename, const char* content_type,
|
|||||||
// Encode spec/model to a file using a registered encoder.
|
// Encode spec/model to a file using a registered encoder.
|
||||||
// Returns the number of bytes written on success, -1 on failure.
|
// Returns the number of bytes written on success, -1 on failure.
|
||||||
// Nullable: m, vfs, error
|
// Nullable: m, vfs, error
|
||||||
MJAPI int mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
|
MJAPI mjtSize mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
|
||||||
const char* content_type, const mjVFS* vfs, char* error,
|
const char* content_type, const mjVFS* vfs, char* error,
|
||||||
int error_sz);
|
int error_sz);
|
||||||
|
|
||||||
// Compile spec to model.
|
// Compile spec to model.
|
||||||
// Nullable: vfs
|
// Nullable: vfs
|
||||||
|
|||||||
@@ -436,7 +436,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
|||||||
('mj_encode',
|
('mj_encode',
|
||||||
FunctionDecl(
|
FunctionDecl(
|
||||||
name='mj_encode',
|
name='mj_encode',
|
||||||
return_type=ValueType(name='int'),
|
return_type=ValueType(name='mjtSize'),
|
||||||
parameters=(
|
parameters=(
|
||||||
FunctionParameterDecl(
|
FunctionParameterDecl(
|
||||||
name='s',
|
name='s',
|
||||||
|
|||||||
@@ -545,7 +545,7 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
"encode",
|
"encode",
|
||||||
[](MjSpec& self, std::string filename,
|
[](MjSpec& self, std::string filename,
|
||||||
std::optional<py::object> model,
|
std::optional<py::object> model,
|
||||||
std::optional<std::string> content_type) -> int {
|
std::optional<std::string> content_type) -> mjtSize {
|
||||||
raw::MjModel* m = nullptr;
|
raw::MjModel* m = nullptr;
|
||||||
if (model.has_value() && !model->is_none()) {
|
if (model.has_value() && !model->is_none()) {
|
||||||
auto& wrapper =
|
auto& wrapper =
|
||||||
@@ -572,8 +572,8 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
err[0] = '\0';
|
err[0] = '\0';
|
||||||
const char* ct =
|
const char* ct =
|
||||||
content_type.has_value() ? content_type->c_str() : nullptr;
|
content_type.has_value() ? content_type->c_str() : nullptr;
|
||||||
int nbytes = mj_encode(self.ptr, m, filename.c_str(), ct,
|
mjtSize nbytes = mj_encode(self.ptr, m, filename.c_str(), ct,
|
||||||
vfs_ptr, err.data(), err.size());
|
vfs_ptr, err.data(), err.size());
|
||||||
|
|
||||||
if (vfs_ptr) {
|
if (vfs_ptr) {
|
||||||
mj_deleteVFS(vfs_ptr);
|
mj_deleteVFS(vfs_ptr);
|
||||||
|
|||||||
@@ -146,9 +146,9 @@ mjSpec* mj_parse(const char* filename, const char* content_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// encode spec/model to file
|
// encode spec/model to file
|
||||||
int mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
|
mjtSize mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
|
||||||
const char* content_type, const mjVFS* vfs, char* error,
|
const char* content_type, const mjVFS* vfs, char* error,
|
||||||
int error_sz) {
|
int error_sz) {
|
||||||
// TODO(shaves) Move MJCF and URDF to encoders/decoders.
|
// TODO(shaves) Move MJCF and URDF to encoders/decoders.
|
||||||
auto filepath = mujoco::user::FilePath(filename);
|
auto filepath = mujoco::user::FilePath(filename);
|
||||||
if (filepath.Ext() == ".xml" ||
|
if (filepath.Ext() == ".xml" ||
|
||||||
@@ -158,7 +158,7 @@ int mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::filesystem::file_size(filename);
|
return static_cast<mjtSize>(std::filesystem::file_size(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
const mjpEncoder* encoder = mjp_findEncoder(filename, content_type);
|
const mjpEncoder* encoder = mjp_findEncoder(filename, content_type);
|
||||||
@@ -174,7 +174,7 @@ int mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
|
|||||||
memset(&resource, 0, sizeof(resource));
|
memset(&resource, 0, sizeof(resource));
|
||||||
resource.name = const_cast<char*>(filename);
|
resource.name = const_cast<char*>(filename);
|
||||||
|
|
||||||
const int nbytes = encoder->encode(s, m, vfs, &resource);
|
const mjtSize nbytes = encoder->encode(s, m, vfs, &resource);
|
||||||
if (nbytes < 0 || !resource.data) {
|
if (nbytes < 0 || !resource.data) {
|
||||||
if (error) {
|
if (error) {
|
||||||
strncpy(error, "encoder failed", error_sz);
|
strncpy(error, "encoder failed", error_sz);
|
||||||
@@ -197,7 +197,7 @@ int mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
encoder->close_resource(&resource);
|
encoder->close_resource(&resource);
|
||||||
|
|
||||||
if (static_cast<int>(written) != nbytes) {
|
if (static_cast<mjtSize>(written) != nbytes) {
|
||||||
if (error) {
|
if (error) {
|
||||||
strncpy(error, "failed to write all bytes to file", error_sz);
|
strncpy(error, "failed to write all bytes to file", error_sz);
|
||||||
error[error_sz - 1] = '\0';
|
error[error_sz - 1] = '\0';
|
||||||
|
|||||||
@@ -306,8 +306,8 @@ std::unordered_map<std::string, AssetEntry> CollectAssets(
|
|||||||
return archive_entries;
|
return archive_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MjzEncode(const mjSpec* spec, const mjModel* model, const mjVFS* vfs,
|
mjtSize MjzEncode(const mjSpec* spec, const mjModel* model, const mjVFS* vfs,
|
||||||
mjResource* resource) {
|
mjResource* resource) {
|
||||||
if (!spec || !resource) {
|
if (!spec || !resource) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -399,7 +399,7 @@ int MjzEncode(const mjSpec* spec, const mjModel* model, const mjVFS* vfs,
|
|||||||
|
|
||||||
resource->data = archive_buf;
|
resource->data = archive_buf;
|
||||||
|
|
||||||
return static_cast<int>(archive_size);
|
return static_cast<mjtSize>(archive_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MjzCloseResource(mjResource* resource) {
|
void MjzCloseResource(mjResource* resource) {
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ struct FakeEncoderOutput {
|
|||||||
char resource_name[512];
|
char resource_name[512];
|
||||||
};
|
};
|
||||||
|
|
||||||
int FakeEncode(const mjSpec* s, const mjModel* m, const mjVFS* vfs,
|
mjtSize FakeEncode(const mjSpec* s, const mjModel* m, const mjVFS* vfs,
|
||||||
mjResource* resource) {
|
mjResource* resource) {
|
||||||
auto* output = new FakeEncoderOutput;
|
auto* output = new FakeEncoderOutput;
|
||||||
output->nbody = m->nbody;
|
output->nbody = m->nbody;
|
||||||
output->ngeom = m->ngeom;
|
output->ngeom = m->ngeom;
|
||||||
@@ -43,7 +43,7 @@ int FakeEncode(const mjSpec* s, const mjModel* m, const mjVFS* vfs,
|
|||||||
std::snprintf(output->resource_name, sizeof(output->resource_name), "%s",
|
std::snprintf(output->resource_name, sizeof(output->resource_name), "%s",
|
||||||
resource->name);
|
resource->name);
|
||||||
resource->data = output;
|
resource->data = output;
|
||||||
return sizeof(FakeEncoderOutput);
|
return static_cast<mjtSize>(sizeof(FakeEncoderOutput));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloseResource(mjResource* resource) {
|
void CloseResource(mjResource* resource) {
|
||||||
|
|||||||
@@ -6690,7 +6690,7 @@ public static unsafe extern void mj_clearCache(mjCache_* cache);
|
|||||||
public static unsafe extern mjModel_* mj_loadXML([MarshalAs(UnmanagedType.LPStr)]string filename, void* vfs, StringBuilder error, int error_sz);
|
public static unsafe extern mjModel_* mj_loadXML([MarshalAs(UnmanagedType.LPStr)]string filename, void* vfs, StringBuilder error, int error_sz);
|
||||||
|
|
||||||
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static unsafe extern int mj_encode(void* s, mjModel_* m, [MarshalAs(UnmanagedType.LPStr)]string filename, [MarshalAs(UnmanagedType.LPStr)]string content_type, void* vfs, StringBuilder error, int error_sz);
|
public static unsafe extern UInt64 mj_encode(void* s, mjModel_* m, [MarshalAs(UnmanagedType.LPStr)]string filename, [MarshalAs(UnmanagedType.LPStr)]string content_type, void* vfs, StringBuilder error, int error_sz);
|
||||||
|
|
||||||
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static unsafe extern int mj_saveLastXML([MarshalAs(UnmanagedType.LPStr)]string filename, mjModel_* m, StringBuilder error, int error_sz);
|
public static unsafe extern int mj_saveLastXML([MarshalAs(UnmanagedType.LPStr)]string filename, mjModel_* m, StringBuilder error, int error_sz);
|
||||||
|
|||||||
Reference in New Issue
Block a user