Change mjSpec and mjModel signature mechanism.

The signature now contains the necessary information to safely perform `bind`. The private UIDs are now removed.

Fixes an issue of changing signature when compiling a copy of an mjSpec.

PiperOrigin-RevId: 744670626
Change-Id: Id3c66419cf2afbe78e91bc4b37d2299f5ec00ab1
This commit is contained in:
Alessio Quaglino
2025-04-07 04:20:17 -07:00
committed by Copybara-Service
parent 93251f07d9
commit cc2f57d820
7 changed files with 85 additions and 40 deletions
+76 -20
View File
@@ -201,7 +201,6 @@ mjCModel::mjCModel() {
world->mass = 0;
mjuu_zerovec(world->inertia, 3);
world->id = 0;
world->uid = GetUid();
world->parent = nullptr;
world->weldid = 0;
world->name = "world";
@@ -297,7 +296,6 @@ void mjCModel::CopyList(std::vector<T*>& dest,
// copy the element from the other model to this model
if (deepcopy_) {
source[i]->ForgetKeyframes();
candidate->uid = source[i]->uid;
} else {
candidate->AddRef();
}
@@ -1038,7 +1036,6 @@ template <class T>
T* mjCModel::AddObject(vector<T*>& list, string type) {
T* obj = new T(this);
obj->id = (int)list.size();
obj->uid = GetUid();
list.push_back(obj);
spec.element->signature = Signature();
return obj;
@@ -1051,7 +1048,6 @@ T* mjCModel::AddObjectDefault(vector<T*>& list, string type, mjCDef* def) {
T* obj = new T(this, def ? def : defaults_[0]);
obj->id = (int)list.size();
obj->classname = def ? def->name : "main";
obj->uid = GetUid();
list.push_back(obj);
spec.element->signature = Signature();
return obj;
@@ -3615,7 +3611,7 @@ void mjCModel::SaveState(const std::string& state_name, const T* qpos, const T*
}
for (auto body : bodies_) {
if (!body->spec.mocap) {
if (!body->spec.mocap || body->mocapid == -1) {
continue;
}
if (mpos) {
@@ -4388,6 +4384,9 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
bodies_[i]->subtreedofs = 0;
}
// initialize spec signature (needed if the user changed sensor or joint types)
spec.element->signature = Signature();
// fill missing names and check that they are all filled
for (const auto& asset : meshes_) asset->CopyFromSpec();
for (const auto& asset : skins_) asset->CopyFromSpec();
@@ -4651,7 +4650,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
// special cases that are not caused by user edits
if (compiler.fusestatic || compiler.discardvisual ||
!spec.element->signature || !pairs_.empty() || !excludes_.empty()) {
!pairs_.empty() || !excludes_.empty()) {
spec.element->signature = m->signature;
}
@@ -4663,21 +4662,78 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
uint64_t mjCModel::Signature() {
std::string uid_str;
for (int i = 0; i < mjNOBJECT; ++i) {
if (i == mjOBJ_XBODY || i == mjOBJ_UNKNOWN || i == mjOBJ_DOF) {
continue;
}
if (object_lists_[i] == nullptr) {
throw mjCError(0, "object list %s is null", std::to_string(i).c_str());
}
uid_str += '|';
for (mjCBase* object : *object_lists_[i]) {
uid_str += std::to_string(object->uid) + " ";
}
std::string mjCModel::PrintTree(const mjCBody* body, std::string indent) {
std::string tree;
tree += indent + "<body>\n";
indent += " ";
for (const auto& joint : body->joints) {
tree += indent + "<joint>" + std::to_string(joint->nq()) + "</joint>\n";
}
return mj_hashString(uid_str.c_str(), UINT64_MAX);
for (uint64_t i = 0; i < body->geoms.size(); ++i) {
tree += indent + "<geom/>\n";
}
for (uint64_t i = 0; i < body->sites.size(); ++i) {
tree += indent + "<site/>\n";
}
for (uint64_t i = 0; i < body->cameras.size(); ++i) {
tree += indent + "<camera/>\n";
}
for (uint64_t i = 0; i < body->lights.size(); ++i) {
tree += indent + "<light/>\n";
}
for (uint64_t i = 0; i < body->bodies.size(); ++i) {
tree += PrintTree(body->bodies[i], indent);
}
indent.pop_back();
indent.pop_back();
tree += indent + "</body>\n";
return tree;
}
uint64_t mjCModel::Signature() {
std::string tree = "\n" + PrintTree(bodies_[0]);
for (unsigned int i = 0; i < flexes_.size(); ++i) {
tree += "<flex/>\n";
}
for (unsigned int i = 0; i < meshes_.size(); ++i) {
tree += "<mesh/>\n";
}
for (unsigned int i = 0; i < skins_.size(); ++i) {
tree += "<skin/>\n";
}
for (unsigned int i = 0; i < hfields_.size(); ++i) {
tree += "<heightfield/>\n";
}
for (unsigned int i = 0; i < textures_.size(); ++i) {
tree += "<texture/>\n";
}
for (unsigned int i = 0; i < materials_.size(); ++i) {
tree += "<material/>\n";
}
for (unsigned int i = 0; i < pairs_.size(); ++i) {
tree += "<pair/>\n";
}
for (unsigned int i = 0; i < excludes_.size(); ++i) {
tree += "<exclude/>\n";
}
for (unsigned int i = 1; i < equalities_.size(); ++i) {
tree += "<equality/>\n";
}
for (unsigned int i = 0; i < tendons_.size(); ++i) {
tree += "<tendon/>\n";
}
for (unsigned int i = 0; i < actuators_.size(); ++i) {
tree += "<actuator/>\n";
}
for (unsigned int i = 0; i < sensors_.size(); ++i) {
tree += "<sensor>" + std::to_string(sensors_[i]->spec.type) + "<sensor/>\n";
}
for (unsigned int i = 0; i < keys_.size(); ++i) {
tree += "<key/>\n";
}
return mj_hashString(tree.c_str(), UINT64_MAX);
}