Initial Implementation of MuJoCo Physics Device

1) Modifications to MJCModel and URDF parsing to enable loading multiple URDF's
2) Device Skeleton for MuJoCo Physics Device
3) Scene Loading and Modifications
4) State Generation

PiperOrigin-RevId: 539676439
Change-Id: Ic65f812b660319443e74f68acd851dba1435ddca
This commit is contained in:
DeepMind
2023-06-12 09:27:33 -07:00
committed by Copybara-Service
parent f67e359532
commit b873800ab3
3 changed files with 55 additions and 10 deletions
+6
View File
@@ -333,6 +333,12 @@ mjCModel* mjParseXML(const char* filename, int vfs_provider, char* error, int er
else if (!strcasecmp(root->Value(), "robot")) { else if (!strcasecmp(root->Value(), "robot")) {
// parse URDF model // parse URDF model
mjXURDF parser; mjXURDF parser;
// set reasonable default for parsing a URDF
// this is separate from the Parser to allow multiple URDFs to be loaded.
model->strippath = true;
model->fusestatic = true;
parser.SetModel(model); parser.SetModel(model);
parser.Parse(root); parser.Parse(root);
} }
+44 -10
View File
@@ -68,18 +68,25 @@ void mjXURDF::Clear(void) {
urGeomNames.clear(); urGeomNames.clear();
} }
std::string mjXURDF::GetPrefixedName(const std::string& name) {
if (name.empty()) {
return name;
}
if (urPrefix.empty()) {
return name;
}
return urPrefix + "/" + name;
}
// actual parser // actual parser
void mjXURDF::Parse(XMLElement* root) { void mjXURDF::Parse(XMLElement* root, const std::string& prefix, double* pos, double* quat) {
std::string name, text; std::string name, text;
XMLElement *elem, *temp; XMLElement *elem, *temp;
int id_parent, id_child; int id_parent, id_child;
urPrefix = prefix;
// set compiler defaults suitable for URDF // set compiler defaults suitable for URDF
model->strippath = true;
model->discardvisual = true; model->discardvisual = true;
model->fusestatic = true;
// parse MuJoCo sections (not part of URDF) // parse MuJoCo sections (not part of URDF)
XMLElement* mjc = FindSubElem(root, "mujoco"); XMLElement* mjc = FindSubElem(root, "mujoco");
@@ -114,6 +121,7 @@ void mjXURDF::Parse(XMLElement* root) {
name = elem->Value(); name = elem->Value();
if (name=="link") { if (name=="link") {
ReadAttrTxt(elem, "name", text, true); ReadAttrTxt(elem, "name", text, true);
text = GetPrefixedName(text);
AddBody(text); AddBody(text);
} }
@@ -130,11 +138,13 @@ void mjXURDF::Parse(XMLElement* root) {
// find parent, get name and id // find parent, get name and id
temp = FindSubElem(elem, "parent", true); temp = FindSubElem(elem, "parent", true);
ReadAttrTxt(temp, "link", text, true); ReadAttrTxt(temp, "link", text, true);
text = GetPrefixedName(text);
id_parent = FindName(text, urName); id_parent = FindName(text, urName);
// find child, get name and id // find child, get name and id
temp = FindSubElem(elem, "child", true); temp = FindSubElem(elem, "child", true);
ReadAttrTxt(temp, "link", text, true); ReadAttrTxt(temp, "link", text, true);
text = GetPrefixedName(text);
id_child = FindName(text, urName); id_child = FindName(text, urName);
// make sure parent and child exist // make sure parent and child exist
@@ -188,10 +198,25 @@ void mjXURDF::Parse(XMLElement* root) {
// advance to next element // advance to next element
elem = elem->NextSiblingElement(); elem = elem->NextSiblingElement();
} }
// override the pose for the base link and add a free joint
for (int i = 0; i < (int)urName.size(); i++) {
if (urParent[i] < 0) {
mjCBody* pbody = (mjCBody*)model->GetWorld()->FindObject(mjOBJ_BODY, urName[i]);
mjuu_copyvec(pbody->pos, pos, 3);
mjuu_copyvec(pbody->quat, quat, 4);
// add a free joint to allow motion of the body
// if the mass is 0, assume the object is static
if (pbody->mass > 0) {
auto pjoint = pbody->AddJoint();
pjoint->name = urName[i] + "_free_joint";
pjoint->type = mjJNT_FREE;
}
}
}
} }
// parse body/link // parse body/link
void mjXURDF::Body(XMLElement* body_elem) { void mjXURDF::Body(XMLElement* body_elem) {
std::string name, text; std::string name, text;
@@ -201,11 +226,11 @@ void mjXURDF::Body(XMLElement* body_elem) {
// get body name and pointer to mjCBody // get body name and pointer to mjCBody
ReadAttrTxt(body_elem, "name", name, true); ReadAttrTxt(body_elem, "name", name, true);
name = GetPrefixedName(name);
pbody = (mjCBody*) model->GetWorld()->FindObject(mjOBJ_BODY, name); pbody = (mjCBody*) model->GetWorld()->FindObject(mjOBJ_BODY, name);
if (!pbody) { if (!pbody) {
throw mjXError(body_elem, "URDF body not found"); // SHOULD NOT OCCUR throw mjXError(body_elem, "URDF body not found"); // SHOULD NOT OCCUR
} }
// inertial element: copy into alternative body frame // inertial element: copy into alternative body frame
if ((elem = FindSubElem(body_elem, "inertial"))) { if ((elem = FindSubElem(body_elem, "inertial"))) {
pbody->explicitinertial = true; pbody->explicitinertial = true;
@@ -264,13 +289,13 @@ void mjXURDF::Body(XMLElement* body_elem) {
// otherwise use material table // otherwise use material table
else { else {
ReadAttrTxt(temp, "name", name, true); ReadAttrTxt(temp, "name", name, true);
name = GetPrefixedName(name);
int imat = FindName(name, urMat); int imat = FindName(name, urMat);
if (imat>=0) { if (imat>=0) {
std::memcpy(rgba, urRGBA[imat].val, 4*sizeof(float)); std::memcpy(rgba, urRGBA[imat].val, 4*sizeof(float));
} }
} }
} }
// create geom if not discarded // create geom if not discarded
if (!model->discardvisual) { if (!model->discardvisual) {
pgeom = Geom(elem, pbody, false); pgeom = Geom(elem, pbody, false);
@@ -282,6 +307,7 @@ void mjXURDF::Body(XMLElement* body_elem) {
// save name if it doesn't already exist. // save name if it doesn't already exist.
mjXUtil::ReadAttrTxt(elem, "name", geom_name); mjXUtil::ReadAttrTxt(elem, "name", geom_name);
name = GetPrefixedName(name);
if (urGeomNames.find(geom_name) == urGeomNames.end()) { if (urGeomNames.find(geom_name) == urGeomNames.end()) {
pgeom->name = geom_name; pgeom->name = geom_name;
urGeomNames.insert(geom_name); urGeomNames.insert(geom_name);
@@ -304,6 +330,7 @@ void mjXURDF::Body(XMLElement* body_elem) {
// save name if it doesn't already exist. // save name if it doesn't already exist.
mjXUtil::ReadAttrTxt(elem, "name", geom_name); mjXUtil::ReadAttrTxt(elem, "name", geom_name);
geom_name = GetPrefixedName(geom_name);
if (urGeomNames.find(geom_name) == urGeomNames.end()) { if (urGeomNames.find(geom_name) == urGeomNames.end()) {
pgeom->name = geom_name; pgeom->name = geom_name;
urGeomNames.insert(geom_name); urGeomNames.insert(geom_name);
@@ -313,13 +340,18 @@ void mjXURDF::Body(XMLElement* body_elem) {
<< std::endl; << std::endl;
} }
} }
// advance // advance
elem = elem->NextSiblingElement(); elem = elem->NextSiblingElement();
} }
} }
void mjXURDF::Parse(XMLElement* root) {
double pos[3] = {0};
mjuu_setvec(pos, 0, 0, 0);
double quat[4] = {1, 0, 0, 0};
mjuu_setvec(quat, 1, 0, 0, 0);
Parse(root, /*prefix=*/"", pos, quat);
}
// parse joint // parse joint
void mjXURDF::Joint(XMLElement* joint_elem) { void mjXURDF::Joint(XMLElement* joint_elem) {
@@ -340,6 +372,7 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
// get parent, check // get parent, check
elem = FindSubElem(joint_elem, "parent", true); elem = FindSubElem(joint_elem, "parent", true);
ReadAttrTxt(elem, "link", name, true); ReadAttrTxt(elem, "link", name, true);
name = GetPrefixedName(name);
parent = (mjCBody*) model->GetWorld()->FindObject(mjOBJ_BODY, name); parent = (mjCBody*) model->GetWorld()->FindObject(mjOBJ_BODY, name);
if (!parent) { // SHOULD NOT OCCUR if (!parent) { // SHOULD NOT OCCUR
throw mjXError(elem, "invalid parent name in URDF joint definition"); throw mjXError(elem, "invalid parent name in URDF joint definition");
@@ -348,6 +381,7 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
// get child=this, check // get child=this, check
elem = FindSubElem(joint_elem, "child", true); elem = FindSubElem(joint_elem, "child", true);
ReadAttrTxt(elem, "link", name, true); ReadAttrTxt(elem, "link", name, true);
name = GetPrefixedName(name);
pbody = (mjCBody*) model->GetWorld()->FindObject(mjOBJ_BODY, name); pbody = (mjCBody*) model->GetWorld()->FindObject(mjOBJ_BODY, name);
if (!pbody) { // SHOULD NOT OCCUR if (!pbody) { // SHOULD NOT OCCUR
throw mjXError(elem, "invalid child name in URDF joint definition"); throw mjXError(elem, "invalid child name in URDF joint definition");
+5
View File
@@ -34,9 +34,12 @@ class mjXURDF : public mjXBase {
mjXURDF(); // constructor mjXURDF(); // constructor
virtual ~mjXURDF(); // destructor virtual ~mjXURDF(); // destructor
// parse and set frame of base link and append a prefix to the name
void Parse(tinyxml2::XMLElement* root, const std::string& prefix, double* pos, double* quat); // parse and set frame of base link
void Parse(tinyxml2::XMLElement* root); // main parser void Parse(tinyxml2::XMLElement* root); // main parser
private: private:
std::string GetPrefixedName(const std::string& name); // get prefix/name of element
int FindName(std::string name, std::vector<std::string>& list); // find name in list int FindName(std::string name, std::vector<std::string>& list); // find name in list
void AddName(std::string name, std::vector<std::string>& list); // add name to list void AddName(std::string name, std::vector<std::string>& list); // add name to list
void AddBody(std::string name); // add body to local table void AddBody(std::string name); // add body to local table
@@ -57,6 +60,8 @@ class mjXURDF : public mjXBase {
std::vector<std::string> urMat; // material name std::vector<std::string> urMat; // material name
std::vector<mjRGBA> urRGBA; // material RBG value std::vector<mjRGBA> urRGBA; // material RBG value
std::unordered_set<std::string> urGeomNames; // geom name std::unordered_set<std::string> urGeomNames; // geom name
std::string urPrefix; // prefix to apply to all names
}; };
#endif // THIRD_PARTY_MUJOCO_SRC_XML_XML_URDF_ #endif // THIRD_PARTY_MUJOCO_SRC_XML_XML_URDF_