@@ -201,6 +201,7 @@ mjCModel::mjCModel() {
201
201
world->mass = 0 ;
202
202
mjuu_zerovec (world->inertia , 3 );
203
203
world->id = 0 ;
204
+ world->uid = GetUid ();
204
205
world->parent = nullptr ;
205
206
world->weldid = 0 ;
206
207
world->name = " world" ;
@@ -213,6 +214,9 @@ mjCModel::mjCModel() {
213
214
214
215
// the source spec is the model itself, overwritten in the copy constructor
215
216
source_spec_ = &spec;
217
+
218
+ // set the signature
219
+ spec.element ->signature = 0 ;
216
220
}
217
221
218
222
@@ -289,6 +293,7 @@ void mjCModel::CopyList(std::vector<T*>& dest,
289
293
// copy the element from the other model to this model
290
294
if (deepcopy_) {
291
295
source[i]->ForgetKeyframes ();
296
+ candidate->uid = GetUid ();
292
297
} else {
293
298
candidate->AddRef ();
294
299
}
@@ -499,6 +504,9 @@ mjCModel& mjCModel::operator+=(const mjCModel& other) {
499
504
nq = nv = na = nu = nmocap = 0 ;
500
505
}
501
506
507
+ // update signature before we reset the tree lists
508
+ spec.element ->signature = Signature ();
509
+
502
510
PointToLocal ();
503
511
return *this ;
504
512
}
@@ -633,6 +641,9 @@ mjCModel& mjCModel::operator-=(const mjCBody& subtree) {
633
641
RemoveFromList (sensors_, oldmodel);
634
642
RemovePlugins ();
635
643
644
+ // update signature before we reset the tree lists
645
+ spec.element ->signature = Signature ();
646
+
636
647
return *this ;
637
648
}
638
649
@@ -803,6 +814,9 @@ void mjCModel::DeleteElement(mjsElement* el) {
803
814
break ;
804
815
}
805
816
817
+ // update signature before we reset the tree lists
818
+ spec.element ->signature = Signature ();
819
+
806
820
ResetTreeLists (); // in case of a nested delete
807
821
MakeTreeLists ();
808
822
ProcessLists (/* checkrepeat=*/ false );
@@ -1019,7 +1033,9 @@ template <class T>
1019
1033
T* mjCModel::AddObject (vector<T*>& list, string type) {
1020
1034
T* obj = new T (this );
1021
1035
obj->id = (int )list.size ();
1036
+ obj->uid = GetUid ();
1022
1037
list.push_back (obj);
1038
+ spec.element ->signature = Signature ();
1023
1039
return obj;
1024
1040
}
1025
1041
@@ -1030,7 +1046,9 @@ T* mjCModel::AddObjectDefault(vector<T*>& list, string type, mjCDef* def) {
1030
1046
T* obj = new T (this , def ? def : defaults_[0 ]);
1031
1047
obj->id = (int )list.size ();
1032
1048
obj->classname = def ? def->name : " main" ;
1049
+ obj->uid = GetUid ();
1033
1050
list.push_back (obj);
1051
+ spec.element ->signature = Signature ();
1034
1052
return obj;
1035
1053
}
1036
1054
@@ -4572,6 +4590,28 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
4572
4590
mju::strcpy_arr (errInfo.message , warningtext);
4573
4591
errInfo.warning = true ;
4574
4592
}
4593
+
4594
+ // save signature
4595
+ m->signature = Signature ();
4596
+ }
4597
+
4598
+
4599
+
4600
+ uint64_t mjCModel::Signature () {
4601
+ std::string uid_str;
4602
+ for (int i = 0 ; i < mjNOBJECT; ++i) {
4603
+ if (i == mjOBJ_XBODY || i == mjOBJ_UNKNOWN || i == mjOBJ_DOF) {
4604
+ continue ;
4605
+ }
4606
+ if (object_lists_[i] == nullptr ) {
4607
+ throw mjCError (0 , " object list %s is null" , std::to_string (i).c_str ());
4608
+ }
4609
+ uid_str += ' |' ;
4610
+ for (mjCBase* object : *object_lists_[i]) {
4611
+ uid_str += std::to_string (object->uid ) + " " ;
4612
+ }
4613
+ }
4614
+ return mj_hashString (uid_str.c_str (), UINT64_MAX);
4575
4615
}
4576
4616
4577
4617
0 commit comments