diff --git a/include/openrave/kinbody.h b/include/openrave/kinbody.h index 3a4c0da518..1fb776fab6 100644 --- a/include/openrave/kinbody.h +++ b/include/openrave/kinbody.h @@ -349,7 +349,6 @@ class OPENRAVE_API KinBody : public InterfaceBase CLA_CheckLimitsThrow = 3, ///< check the limits and throws if something went wrong }; - /// \brief Describes the properties of a geometric primitive. /// /// Contains everything associated with a geometry's appearance and shape @@ -982,6 +981,33 @@ class OPENRAVE_API KinBody : public InterfaceBase typedef boost::shared_ptr GeometryPtr; typedef boost::shared_ptr GeometryConstPtr; + /// \brief Describes the properties of an extraGeometric primitive. + class OPENRAVE_API ExtraGeometryInfo : public InfoBase + { +public: + ExtraGeometryInfo(){ + } + + void Reset() override; + void SerializeJSON(rapidjson::Value &value, rapidjson::Document::AllocatorType& allocator, dReal fUnitScale, int options) const override; + void DeserializeJSON(const rapidjson::Value &value, dReal fUnitScale, int options) override; + + std::vector _vgeometryinfos; + + ///\brief unique id of the extrageometry + std::string _id; + /// \brief unique extrageometry name + std::string _name; + +private: + friend class Link; + friend class KinBody; + friend class RobtBase; + }; + + typedef boost::shared_ptr ExtraGeometryInfoPtr; + typedef boost::shared_ptr ExtraGeometryInfoConstPtr; + /// \brief Describes the properties of a link used to initialize it class OPENRAVE_API LinkInfo : public InfoBase { @@ -1017,7 +1043,7 @@ class OPENRAVE_API KinBody : public InterfaceBase std::vector _vgeometryinfos; /// extra-purpose geometries like /// self - self-collision specific geometry. By default, this type of geometry will be always set - std::map< std::string, std::vector > _mapExtraGeometries; + std::map< std::string, ExtraGeometryInfoPtr > _mapExtraGeometries; ///\brief unique id of the link std::string _id; @@ -1086,6 +1112,8 @@ class OPENRAVE_API KinBody : public InterfaceBase /// \brief deserializes a readable from rReadable and stores it into _mReadableInterfaces[id] void _DeserializeReadableInterface(const std::string& id, const rapidjson::Value& rReadable, dReal fUnitScale); + void _DeserializeExtraGeometryInfo(const std::string& id, const rapidjson::Value& rExtraGeom, dReal fUnitScale, int options); + friend class Link; friend class KinBody; friend class RobtBase; @@ -1329,21 +1357,21 @@ class OPENRAVE_API KinBody : public InterfaceBase /// \brief initializes the link with geometries from the extra geomeries in LinkInfo /// - /// \param name The name of the geometry group. If name is empty, will initialize the default geometries. - /// \throw If name does not exist in GetInfo()._mapExtraGeometries, then throw an exception. - void SetGeometriesFromGroup(const std::string& name); + /// \param groupid The id of the geometry group. If id is empty, will initialize the default geometries. + /// \throw If id does not exist in GetInfo()._mapExtraGeometries, then throw an exception. + void SetGeometriesFromGroup(const std::string& groupid); /// \brief returns a const reference to the vector of geometries for a particular group /// - /// \param name The name of the geometry group. + /// \param groupid The id of the geometry group. /// \throw openrave_exception If the group does not exist, throws an exception. - const std::vector& GetGeometriesFromGroup(const std::string& name) const; + const std::vector& GetGeometriesFromGroup(const std::string& groupid) const; /// \brief stores geometries for later retrieval /// /// the list is stored inside _GetInfo()._mapExtraGeometries. Note that the pointers are copied and not the data, so /// any be careful not to modify the geometries afterwards - void SetGroupGeometries(const std::string& name, const std::vector& geometries); + void SetGroupGeometries(const std::string& groupid, const std::vector& geometries); private: /// \brief stores geometries for later retrieval diff --git a/include/openrave/openrave.h b/include/openrave/openrave.h index 66ee955937..1670c65831 100644 --- a/include/openrave/openrave.h +++ b/include/openrave/openrave.h @@ -58,6 +58,7 @@ #if __cplusplus >= 201703L #include #else +#include #include namespace std{ // make boost::string_view handlable by std::unordered_set/map diff --git a/python/bindings/include/openravepy/openravepy_int.h b/python/bindings/include/openravepy/openravepy_int.h index 24fcf43ef0..084d555c0a 100644 --- a/python/bindings/include/openravepy/openravepy_int.h +++ b/python/bindings/include/openravepy/openravepy_int.h @@ -100,6 +100,7 @@ class PyCameraIntrinsics; class PyLinkInfo; class PyJointInfo; class PyGeometryInfo; +class PyExtraGeometryInfo; class PyManipulatorInfo; class PyAttachedSensorInfo; class PyConnectedBodyInfo; @@ -150,6 +151,7 @@ typedef OPENRAVE_SHARED_PTR PyCameraIntrinsicsPtr; typedef OPENRAVE_SHARED_PTR PyLinkInfoPtr; typedef OPENRAVE_SHARED_PTR PyJointInfoPtr; typedef OPENRAVE_SHARED_PTR PyGeometryInfoPtr; +typedef OPENRAVE_SHARED_PTR PyExtraGeometryInfoPtr; typedef OPENRAVE_SHARED_PTR PyManipulatorInfoPtr; typedef OPENRAVE_SHARED_PTR PyAttachedSensorInfoPtr; typedef OPENRAVE_SHARED_PTR PyConnectedBodyInfoPtr; @@ -889,6 +891,7 @@ OPENRAVEPY_API PyJointPtr toPyJoint(KinBody::JointPtr pjoint, PyEnvironmentBaseP OPENRAVEPY_API PyLinkInfoPtr toPyLinkInfo(const KinBody::LinkInfo& linkinfo); OPENRAVEPY_API PyJointInfoPtr toPyJointInfo(const KinBody::JointInfo& jointinfo); OPENRAVEPY_API PyGeometryInfoPtr toPyGeometryInfo(const KinBody::GeometryInfo& geominfo); +OPENRAVEPY_API PyExtraGeometryInfoPtr toPyExtraGeometryInfo(const KinBody::ExtraGeometryInfo& extrageominfo); OPENRAVEPY_API PyManipulatorInfoPtr toPyManipulatorInfo(const RobotBase::ManipulatorInfo& manipulatorinfo); OPENRAVEPY_API PyAttachedSensorInfoPtr toPyAttachedSensorInfo(const RobotBase::AttachedSensorInfo& attachedSensorinfo); OPENRAVEPY_API PyConnectedBodyInfoPtr toPyConnectedBodyInfo(const RobotBase::ConnectedBodyInfo& connectedBodyInfo); diff --git a/python/bindings/include/openravepy/openravepy_jointinfo.h b/python/bindings/include/openravepy/openravepy_jointinfo.h index c66b9189f1..bba85f3ae9 100644 --- a/python/bindings/include/openravepy/openravepy_jointinfo.h +++ b/python/bindings/include/openravepy/openravepy_jointinfo.h @@ -115,6 +115,30 @@ class PyGeometryInfo typedef OPENRAVE_SHARED_PTR PyGeometryInfoPtr; +class PyExtraGeometryInfo +{ +public: + PyExtraGeometryInfo(); + PyExtraGeometryInfo(const KinBody::ExtraGeometryInfo& info); + KinBody::ExtraGeometryInfoPtr GetExtraGeometryInfo(); + + object SerializeJSON(dReal fUnitScale=1.0, object options=py::none_()); + void DeserializeJSON(object obj, dReal fUnitScale=1.0, object options=py::none_()); + + py::list _vgeometryinfos; + + std::string __repr__(); + std::string __str__(); + + object _id = py::none_(); + object _name = py::none_(); + +private: + void _Update(const KinBody::ExtraGeometryInfo& info); +}; + +typedef OPENRAVE_SHARED_PTR PyExtraGeometryInfoPtr; + class PyLinkInfo { public: @@ -403,13 +427,13 @@ class PyLink : public PyReadablesContainer void AddGeometryToGroup(object ogeometryinfo, const std::string& groupname); void RemoveGeometryByName(const std::string& geometryname, bool removeFromAllGroups); - void SetGeometriesFromGroup(const std::string& name); + void SetGeometriesFromGroup(const std::string& groupid); - object GetGeometriesFromGroup(const std::string& name); + object GetGeometriesFromGroup(const std::string& groupid); - void SetGroupGeometries(const std::string& name, object ogeometryinfos); + void SetGroupGeometries(const std::string& groupid, object oextrageometryinfo); - int GetGroupNumGeometries(const std::string& geomname); + int GetGroupNumGeometries(const std::string& groupid); object GetRigidlyAttachedLinks() const; diff --git a/python/bindings/openravepy_kinbody.cpp b/python/bindings/openravepy_kinbody.cpp index 8b4ef9ffc0..667a2cd017 100644 --- a/python/bindings/openravepy_kinbody.cpp +++ b/python/bindings/openravepy_kinbody.cpp @@ -596,6 +596,91 @@ std::string PyGeometryInfo::__str__() return orjson::DumpJson(doc); } +PyExtraGeometryInfo::PyExtraGeometryInfo() +{ +} + +PyExtraGeometryInfo::PyExtraGeometryInfo(const KinBody::ExtraGeometryInfo& info) +{ + _Update(info); +} + +KinBody::ExtraGeometryInfoPtr PyExtraGeometryInfo::GetExtraGeometryInfo() +{ + KinBody::ExtraGeometryInfoPtr pinfo(new KinBody::ExtraGeometryInfo()); + // extract id and name + if ( !IS_PYTHONOBJECT_NONE(_id) ) { + pinfo->_id = py::extract(_id); + } + if( !IS_PYTHONOBJECT_NONE(_name) ) { + pinfo->_name = py::extract(_name); + } + // extract vgeometries field + pinfo->_vgeometryinfos.resize(len(_vgeometryinfos)); + for(size_t i = 0; i < pinfo->_vgeometryinfos.size(); ++i) { + PyGeometryInfoPtr pygeom = py::extract(_vgeometryinfos[i]); + pinfo->_vgeometryinfos[i] = pygeom->GetGeometryInfo(); + } + return pinfo; +} + +py::object PyExtraGeometryInfo::SerializeJSON(dReal fUnitScale, object options) +{ + rapidjson::Document doc; + KinBody::ExtraGeometryInfoPtr pInfo = GetExtraGeometryInfo(); + const int intOptions = pyGetIntFromPy(options, 0); + { + openravepy::PythonThreadSaver threadsaver; + pInfo->SerializeJSON(doc, doc.GetAllocator(), fUnitScale, intOptions); + } + return toPyObject(doc); +} + +void PyExtraGeometryInfo::DeserializeJSON(object obj, dReal fUnitScale, py::object options) +{ + rapidjson::Document doc; + toRapidJSONValue(obj, doc, doc.GetAllocator()); + KinBody::ExtraGeometryInfoPtr pInfo = GetExtraGeometryInfo(); + const int intOptions = pyGetIntFromPy(options, 0); + { + openravepy::PythonThreadSaver threadsaver; + pInfo->DeserializeJSON(doc, fUnitScale, intOptions); + } + _Update(*pInfo); +} + +std::string PyExtraGeometryInfo::__repr__() +{ + rapidjson::Document doc; + KinBody::ExtraGeometryInfoPtr pextrageominfo = GetExtraGeometryInfo(); + dReal fUnitScale = 1; + int options = 0; + pextrageominfo->SerializeJSON(doc, doc.GetAllocator(), fUnitScale, options); + std::string repr("ExtraGeometryInfo('"); + repr += orjson::DumpJson(doc); + repr += "')"; + return repr; +} + +std::string PyExtraGeometryInfo::__str__() +{ + rapidjson::Document doc; + KinBody::ExtraGeometryInfoPtr pextrageominfo = GetExtraGeometryInfo(); + dReal fUnitScale = 1; + int options = 0; + pextrageominfo->SerializeJSON(doc, doc.GetAllocator(), fUnitScale, options); + return orjson::DumpJson(doc); +} + +void PyExtraGeometryInfo::_Update(const KinBody::ExtraGeometryInfo& info) +{ + _id = ConvertStringToUnicode(info._id); + _name = ConvertStringToUnicode(info._name); + FOREACHC(itgeominfo, info._vgeometryinfos) { + _vgeometryinfos.append(PyGeometryInfoPtr(new PyGeometryInfo(**itgeominfo))); + } +} + PyLinkInfo::PyLinkInfo() { } @@ -627,7 +712,7 @@ void PyLinkInfo::_Update(const KinBody::LinkInfo& info) { vForcedAdjacentLinks.append(linkName); } FOREACHC(it, info._mapExtraGeometries) { - _mapExtraGeometries[it->first.c_str()] = toPyArray(it->second); + _mapExtraGeometries[it->first.c_str()] = toPyExtraGeometryInfo(*(it->second)); } _vForcedAdjacentLinks = vForcedAdjacentLinks; _bStatic = info._bStatic; @@ -669,6 +754,11 @@ KinBody::LinkInfoPtr PyLinkInfo::GetLinkInfo() { PyGeometryInfoPtr pygeom = py::extract(_vgeometryinfos[i]); info._vgeometryinfos[i] = pygeom->GetGeometryInfo(); } + for(const std::pair& item : _mapExtraGeometries) { + std::string id = extract(item.first); + PyExtraGeometryInfoPtr pyextrageom = py::extract(item.second); + info._mapExtraGeometries[id] = pyextrageom->GetExtraGeometryInfo(); + } if( !IS_PYTHONOBJECT_NONE(_id) ) { info._id = py::extract(_id); } @@ -680,6 +770,23 @@ KinBody::LinkInfoPtr PyLinkInfo::GetLinkInfo() { info._mass = _mass; info._vinertiamoments = ExtractVector3(_vinertiamoments); info._mapFloatParameters.clear(); + +#ifdef USE_PYBIND11_PYTHON_BINDINGS + for(const std::pair& item : _mapExtraGeometries) { + std::string id = extract(item.first); + PyExtraGeometryInfoPtr pyextrageom = py::extract(item.second); + info._mapExtraGeometries[id] = pyextrageom->GetExtraGeometryInfo(); + } +#else + size_t num = len(_mapExtraGeometries); + object okeyvalueiter = _mapExtraGeometries.iteritems(); + for(size_t i = 0; i < num; ++i) { + object okeyvalue = okeyvalueiter.attr("next") (); + std::string id = extract(okeyvalue[0]); + info._mapExtraGeometries[id] = py::extrqact(okeyvalue[1]); + } +#endif + #ifdef USE_PYBIND11_PYTHON_BINDINGS for(const std::pair& item : _mapFloatParameters) { std::string name = extract(item.first); @@ -727,29 +834,6 @@ KinBody::LinkInfoPtr PyLinkInfo::GetLinkInfo() { } #endif -#ifdef USE_PYBIND11_PYTHON_BINDINGS - for(const std::pair& item : _mapExtraGeometries) { - std::string name = extract(item.first); - info._mapExtraGeometries[name] = std::vector(); info._mapExtraGeometries[name].reserve(len(item.second)); - for(size_t j = 0; j < len(item.second); j++) { - PyGeometryInfoPtr pygeom = py::extract(item.second[py::to_object(j)]); - info._mapExtraGeometries[name].push_back(pygeom->GetGeometryInfo()); - } - } -#else - num = len(_mapExtraGeometries); - okeyvalueiter = _mapExtraGeometries.iteritems(); - for(size_t i = 0; i < num; ++i) { - object okeyvalue = okeyvalueiter.attr("next") (); - std::string name = extract(okeyvalue[0]); - info._mapExtraGeometries[name] = std::vector(); info._mapExtraGeometries[name].reserve(len(okeyvalue[1])); - for(size_t j = 0; j < (size_t)len(okeyvalue[1]); j++) { - PyGeometryInfoPtr pygeom = py::extract(okeyvalue[1][j]); - info._mapExtraGeometries[name].push_back(pygeom->GetGeometryInfo()); - } - } -#endif - info._mReadableInterfaces = ExtractReadableInterfaces(_readableInterfaces); info._vForcedAdjacentLinks = ExtractArray(_vForcedAdjacentLinks); info._bStatic = _bStatic; @@ -1877,36 +1961,36 @@ void PyLink::RemoveGeometryByName(const std::string& geometryname, bool removeFr _plink->RemoveGeometryByName(geometryname, removeFromAllGroups); } -void PyLink::SetGeometriesFromGroup(const std::string& name) +void PyLink::SetGeometriesFromGroup(const std::string& groupid) { - _plink->SetGeometriesFromGroup(name); + _plink->SetGeometriesFromGroup(groupid); } -object PyLink::GetGeometriesFromGroup(const std::string& name) +object PyLink::GetGeometriesFromGroup(const std::string& groupid) { py::list ogeometryinfos; - FOREACHC(itinfo, _plink->GetGeometriesFromGroup(name)) { + FOREACHC(itinfo, _plink->GetGeometriesFromGroup(groupid)) { ogeometryinfos.append(PyGeometryInfoPtr(new PyGeometryInfo(**itinfo))); } return ogeometryinfos; } -void PyLink::SetGroupGeometries(const std::string& name, object ogeometryinfos) +void PyLink::SetGroupGeometries(const std::string& groupid, object ogeometryinfos) { std::vector geometries(len(ogeometryinfos)); - for(size_t i = 0; i < geometries.size(); ++i) { + for (size_t i = 0; i < geometries.size(); ++i) { PyGeometryInfoPtr pygeom = py::extract(ogeometryinfos[py::to_object(i)]); - if( !pygeom ) { + if ( !pygeom ) { throw OPENRAVE_EXCEPTION_FORMAT0(_("cannot cast to KinBody.GeometryInfo"),ORE_InvalidArguments); } geometries[i] = pygeom->GetGeometryInfo(); } - _plink->SetGroupGeometries(name, geometries); + _plink->SetGroupGeometries(groupid, geometries); } -int PyLink::GetGroupNumGeometries(const std::string& geomname) +int PyLink::GetGroupNumGeometries(const std::string& groupid) { - return _plink->GetGroupNumGeometries(geomname); + return _plink->GetGroupNumGeometries(groupid); } object PyLink::GetRigidlyAttachedLinks() const { @@ -2379,6 +2463,11 @@ PyGeometryInfoPtr toPyGeometryInfo(const KinBody::GeometryInfo& geominfo) return PyGeometryInfoPtr(new PyGeometryInfo(geominfo)); } +PyExtraGeometryInfoPtr toPyExtraGeometryInfo(const KinBody::ExtraGeometryInfo& extrageominfo) +{ + return PyExtraGeometryInfoPtr(new PyExtraGeometryInfo(extrageominfo)); +} + py::object toPyObject(const PyGeometryInfoPtr& pygeom) { return py::to_object(pygeom); @@ -4913,12 +5002,14 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(GetGrabbedInfo_overloads, GetGrabbedInfo, // SerializeJSON BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyElectricMotorActuatorInfo_SerializeJSON_overloads, SerializeJSON, 0, 2) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyGeometryInfo_SerializeJSON_overloads, SerializeJSON, 0, 2) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyExtraGeometryInfo_SerializeJSON_overloads, SerializeJSON, 0, 2) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyLinkInfo_SerializeJSON_overloads, SerializeJSON, 0, 2) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyJointInfo_SerializeJSON_overloads, SerializeJSON, 0, 2) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyGrabbedInfo_SerializeJSON_overloads, SerializeJSON, 0, 2) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyKinBodyInfo_SerializeJSON_overloads, SerializeJSON, 0, 2) // DeserializeJSON BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyElectricMotorActuatorInfo_DeserializeJSON_overloads, DeserializeJSON, 1, 3) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyExtraGeometryInfo_DeserializeJSON_overloads, DeserializeJSON, 1, 3) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyGeometryInfo_DeserializeJSON_overloads, DeserializeJSON, 1, 3) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyLinkInfo_DeserializeJSON_overloads, DeserializeJSON, 1, 3) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PyJointInfo_DeserializeJSON_overloads, DeserializeJSON, 1, 3) @@ -5213,6 +5304,35 @@ void init_openravepy_kinbody() #endif ; +#ifdef USE_PYBIND11_PYTHON_BINDINGS + object extrageometryinfo = class_ >(m, "ExtraGeometryInfo", DOXY_CLASS(KinBody::ExtraGeometryInfo)) + .def(init<>()) +#else + object extrageometryinfo = class_ >("ExtraGeometryInfo", DOXY_CLASS(KinBody::ExtraGeometryInfo)) +#endif + .def_readwrite("_vgeometryinfos", &PyExtraGeometryInfo::_vgeometryinfos) + .def_readwrite("_id", &PyExtraGeometryInfo::_id) + .def_readwrite("_name", &PyExtraGeometryInfo::_name) +#ifdef USE_PYBIND11_PYTHON_BINDINGS + .def("SerializeJSON", &PyExtraGeometryInfo::SerializeJSON, + "unitScale"_a = 1.0, + "options"_a = py::none_(), + DOXY_FN(ExtraGeometryInfo, SerializeJSON) + ) + .def("DeserializeJSON", &PyExtraGeometryInfo::DeserializeJSON, + "obj"_a, + "unitScale"_a = 1.0, + "options"_a = py::none_(), + DOXY_FN(ExtraGeometryInfo, DeserializeJSON) + ) +#else + .def("SerializeJSON", &ExtraGeometryInfo::SerializeJSON, PyExtraGeometryInfo_SerializeJSON_overloads(PY_ARGS("unitScale", "options") DOXY_FN(ExtraGeometryInfo, SerializeJSON))) + .def("DeserializeJSON", &ExtraGeometryInfo::DeserializeJSON, PyExtraGeometryInfo_DeserializeJSON_overloads(PY_ARGS("obj", "unitScale", "options") DOXY_FN(ExtraGeometryInfo, DeserializeJSON))) +#endif + .def("__repr__", &PyExtraGeometryInfo::__repr__) + .def("__str__", &PyExtraGeometryInfo::__str__) + ; + #ifdef USE_PYBIND11_PYTHON_BINDINGS object sidewall = class_ >(m, "SideWall", DOXY_CLASS(KinBody::GeometryInfo::SideWall)) .def(init<>()) @@ -6276,6 +6396,7 @@ void init_openravepy_kinbody() // \deprecated (12/10/18) link.attr("GeomType") = geometrytype; link.attr("GeometryInfo") = geometryinfo; + link.attr("ExtraGeometryInfo") = extrageometryinfo; { #ifdef USE_PYBIND11_PYTHON_BINDINGS // PyGeometry belongs to PyLink, not openravepy._openravepy_.openravepy_int diff --git a/src/libopenrave-core/colladaparser/colladawriter.cpp b/src/libopenrave-core/colladaparser/colladawriter.cpp index 053bd1ce8f..5dcbe04ea3 100644 --- a/src/libopenrave-core/colladaparser/colladawriter.cpp +++ b/src/libopenrave-core/colladaparser/colladawriter.cpp @@ -2825,7 +2825,7 @@ class ColladaWriter : public daeErrorHandler } FOREACHC(itgeomgroup, (*itlink)->GetInfo()._mapExtraGeometries) { int igeom = 0; - FOREACHC(itgeominfo, itgeomgroup->second) { + FOREACHC(itgeominfo, itgeomgroup->second->_vgeometryinfos) { daeElementRef bind_instance_geometry = ptec->add("bind_instance_geometry"); bind_instance_geometry->setAttribute("type", itgeomgroup->first.c_str()); bind_instance_geometry->setAttribute("link", vlinksidrefs.at((*itlink)->GetIndex()).c_str()); diff --git a/src/libopenrave-core/xmlreaders-core.cpp b/src/libopenrave-core/xmlreaders-core.cpp index c54bea2bf8..876dce8b89 100644 --- a/src/libopenrave-core/xmlreaders-core.cpp +++ b/src/libopenrave-core/xmlreaders-core.cpp @@ -976,7 +976,12 @@ class LinkXMLReader : public StreamXMLReader // geometry is not in the default group, so we add it to the LinkInfo without instantiating it string groupname = geomreader->GetGroupName(); if( groupname != "self" ) { - _plink->_info._mapExtraGeometries[groupname].push_back(info); + if (_plink->_info._mapExtraGeometries.find(groupname) == _plink->_info._mapExtraGeometries.end()) { + _plink->_info._mapExtraGeometries[groupname] = KinBody::ExtraGeometryInfoPtr(new KinBody::ExtraGeometryInfo()); + _plink->_info._mapExtraGeometries[groupname]->_id = groupname; + _plink->_info._mapExtraGeometries[groupname]->_name = groupname; + } + _plink->_info._mapExtraGeometries[groupname]->_vgeometryinfos.push_back(info); _pcurreader.reset(); return false; } diff --git a/src/libopenrave/CMakeLists.txt b/src/libopenrave/CMakeLists.txt index e71ebb3239..b21d66c2c4 100644 --- a/src/libopenrave/CMakeLists.txt +++ b/src/libopenrave/CMakeLists.txt @@ -9,6 +9,7 @@ set(openrave_lib_SOURCES interface.cpp kinbody.cpp kinbodycollision.cpp + kinbodyextrageometry.cpp kinbodygeometry.cpp kinbodygrab.cpp kinbodyjoint.cpp diff --git a/src/libopenrave/kinbody.cpp b/src/libopenrave/kinbody.cpp index e081798073..60d478bdc2 100644 --- a/src/libopenrave/kinbody.cpp +++ b/src/libopenrave/kinbody.cpp @@ -685,11 +685,11 @@ void KinBody::SetLinkGeometriesFromGroup(const std::string& geomname, const bool pvinfos = &(*itlink)->_info._vgeometryinfos; } else { - std::map< std::string, std::vector >::iterator it = (*itlink)->_info._mapExtraGeometries.find(geomname); + std::map< std::string, KinBody::ExtraGeometryInfoPtr >::iterator it = (*itlink)->_info._mapExtraGeometries.find(geomname); if( it == (*itlink)->_info._mapExtraGeometries.end() ) { throw OPENRAVE_EXCEPTION_FORMAT(_("could not find geometries %s for link %s"),geomname%GetName(),ORE_InvalidArguments); } - pvinfos = &it->second; + pvinfos = &it->second->_vgeometryinfos; } (*itlink)->_vGeometries.resize(pvinfos->size()); for(size_t i = 0; i < pvinfos->size(); ++i) { @@ -712,12 +712,15 @@ void KinBody::SetLinkGeometriesFromGroup(const std::string& geomname, const bool void KinBody::SetLinkGroupGeometries(const std::string& geomname, const std::vector< std::vector >& linkgeometries) { OPENRAVE_ASSERT_OP( linkgeometries.size(), ==, _veclinks.size() ); - FOREACH(itlink, _veclinks) { + FOREACH(itlink, _veclinks){ Link& link = **itlink; - std::map< std::string, std::vector >::iterator it = link._info._mapExtraGeometries.insert(make_pair(geomname,std::vector())).first; + KinBody::ExtraGeometryInfoPtr new_extrageom( new KinBody::ExtraGeometryInfo() ); + new_extrageom->_id = geomname; + new_extrageom->_name = geomname; + std::map< std::string, KinBody::ExtraGeometryInfoPtr >::iterator it = link._info._mapExtraGeometries.insert(make_pair(geomname, new_extrageom)).first; const std::vector& geometries = linkgeometries.at(link.GetIndex()); - it->second.resize(geometries.size()); - std::copy(geometries.begin(),geometries.end(),it->second.begin()); + it->second->_vgeometryinfos.resize(geometries.size()); + std::copy(geometries.begin(), geometries.end(), it->second->_vgeometryinfos.begin()); } _PostprocessChangedParameters(Prop_LinkGeometryGroup); // have to notify collision checkers that the geometry info they are caching could have changed. } @@ -5143,11 +5146,14 @@ void KinBody::_ComputeInternalInformation() std::string selfgroup("self"); FOREACH(itlink, _veclinks) { if( (*itlink)->_info._mapExtraGeometries.find(selfgroup) == (*itlink)->_info._mapExtraGeometries.end() ) { - std::vector vgeoms; + (*itlink)->_info._mapExtraGeometries[selfgroup] = ExtraGeometryInfoPtr(new ExtraGeometryInfo()); + (*itlink)->_info._mapExtraGeometries[selfgroup]->_id = selfgroup; + (*itlink)->_info._mapExtraGeometries[selfgroup]->_name = selfgroup; + std::vector& vgeoms = (*itlink)->_info._mapExtraGeometries[selfgroup]->_vgeometryinfos; + vgeoms.reserve((*itlink)->_vGeometries.size()); FOREACH(itgeom, (*itlink)->_vGeometries) { vgeoms.push_back(GeometryInfoPtr(new GeometryInfo((*itgeom)->GetInfo()))); } - (*itlink)->_info._mapExtraGeometries.insert(make_pair(selfgroup, vgeoms)); } } @@ -5758,14 +5764,15 @@ void KinBody::Clone(InterfaceBaseConstPtr preference, int cloningoptions) } { // deep copy extra geometries as well, otherwise changing value of map in original map affects value of cloned map - std::map< std::string, std::vector > newMapExtraGeometries; - for (const std::pair >& keyValue : newlink._info._mapExtraGeometries) { - std::vector newvalues; - newvalues.reserve(keyValue.second.size()); - for (const GeometryInfoPtr& geomInfoPtr : keyValue.second) { - newvalues.push_back(GeometryInfoPtr(new GeometryInfo(*geomInfoPtr))); - } - newMapExtraGeometries[keyValue.first] = newvalues; + std::map newMapExtraGeometries; + for (const std::pair& keyValue : newlink._info._mapExtraGeometries) { + newMapExtraGeometries[keyValue.first] = ExtraGeometryInfoPtr(new ExtraGeometryInfo()); + newMapExtraGeometries[keyValue.first]->_id = keyValue.second->_id; + newMapExtraGeometries[keyValue.first]->_name = keyValue.second->_name; + newMapExtraGeometries[keyValue.first]->_vgeometryinfos.reserve(keyValue.second->_vgeometryinfos.size()); + for (const GeometryInfoPtr& geomInfoPtr : keyValue.second->_vgeometryinfos) { + newMapExtraGeometries[keyValue.first]->_vgeometryinfos.push_back(GeometryInfoPtr(new GeometryInfo(*geomInfoPtr))); + } } newlink._info._mapExtraGeometries = newMapExtraGeometries; } diff --git a/src/libopenrave/kinbodyextrageometry.cpp b/src/libopenrave/kinbodyextrageometry.cpp new file mode 100644 index 0000000000..6e72ae50c8 --- /dev/null +++ b/src/libopenrave/kinbodyextrageometry.cpp @@ -0,0 +1,79 @@ +// -*- coding: utf-8 -*- +// Copyright (C) 2006-2014 Rosen Diankov (rosen.diankov@gmail.com) +// +// This file is part of OpenRAVE. +// OpenRAVE is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +#include "libopenrave.h" + +namespace OpenRAVE { + +void KinBody::ExtraGeometryInfo::Reset() +{ + _vgeometryinfos.clear(); + _id.clear(); + _name.clear(); +} + +void KinBody::ExtraGeometryInfo::SerializeJSON(rapidjson::Value &value, rapidjson::Document::AllocatorType& allocator, dReal fUnitScale, int options) const +{ + value.SetObject(); + orjson::SetJsonValueByKey(value, "id", _id, allocator); + orjson::SetJsonValueByKey(value, "name", _name, allocator); + + if (_vgeometryinfos.size() > 0) { + rapidjson::Value geometriesValue; + geometriesValue.SetArray(); + geometriesValue.Reserve(_vgeometryinfos.size(), allocator); + FOREACHC(it, _vgeometryinfos) { + rapidjson::Value geometryValue; + (*it)->SerializeJSON(geometryValue, allocator, fUnitScale, options); + geometriesValue.PushBack(geometryValue, allocator); + } + value.AddMember("geometries", geometriesValue, allocator); + } +} + +void KinBody::ExtraGeometryInfo::DeserializeJSON(const rapidjson::Value &value, dReal fUnitScale, int options) +{ + std::string id; + std::string name; + if (value.HasMember("id")) { + orjson::LoadJsonValueByKey(value, "id", id); + } + if (value.HasMember("name")) { + orjson::LoadJsonValueByKey(value, "name", name); + } + + if (id.empty() && name.empty()) { + RAVELOG_WARN("failed to deserialize the json due to missing or empty id and name"); + return; + } + else if (id.empty()) { + id = name; + } + else if (name.empty()) { + name = id; + } + this->_id = id; + this->_name = name; + + if (value.HasMember("geometries")) { + _vgeometryinfos.reserve(value["geometries"].Size() + _vgeometryinfos.size()); + for (rapidjson::Value::ConstValueIterator it = value["geometries"].Begin(); it != value["geometries"].End(); ++it) { + UpdateOrCreateInfoWithNameCheck(*it, _vgeometryinfos, "name", fUnitScale, options); + } + } +} + +} \ No newline at end of file diff --git a/src/libopenrave/kinbodylink.cpp b/src/libopenrave/kinbodylink.cpp index ebb63fcc5b..f43d12e365 100644 --- a/src/libopenrave/kinbodylink.cpp +++ b/src/libopenrave/kinbodylink.cpp @@ -123,7 +123,7 @@ void KinBody::LinkInfo::ConvertUnitScale(dReal fUnitScale) (*itgeometry)->ConvertUnitScale(fUnitScale); } FOREACH(itextra, _mapExtraGeometries) { - FOREACH(itgeometry, itextra->second) { + FOREACH(itgeometry, itextra->second->_vgeometryinfos) { (*itgeometry)->ConvertUnitScale(fUnitScale); } } @@ -212,24 +212,17 @@ void KinBody::LinkInfo::SerializeJSON(rapidjson::Value &value, rapidjson::Docume value.AddMember("readableInterfaces", std::move(rReadableInterfaces), allocator); } - // if(_mapExtraGeometries.size() > 0 ) { - // rapidjson::Value extraGeometriesValue; - // extraGeometriesValue.SetObject(); - // FOREACHC(im, _mapExtraGeometries) { - // rapidjson::Value geometriesValue; - // geometriesValue.SetArray(); - // FOREACHC(iv, im->second){ - // if(!!(*iv)) - // { - // rapidjson::Value geometryValue; - // (*iv)->SerializeJSON(geometryValue, allocator); - // geometriesValue.PushBack(geometryValue, allocator); - // } - // } - // extraGeometriesValue.AddMember(rapidjson::Value(im->first.c_str(), allocator).Move(), geometriesValue, allocator); - // } - // value.AddMember("extraGeometries", extraGeometriesValue, allocator); - // } + if (_mapExtraGeometries.size() > 0) { + rapidjson::Value extraGeometriesValue; + extraGeometriesValue.SetArray(); + extraGeometriesValue.Reserve(_mapExtraGeometries.size(), allocator); + FOREACHC(im, _mapExtraGeometries) { + rapidjson::Value extraGeometryValue; + im->second->SerializeJSON(extraGeometryValue, allocator, fUnitScale, options); + extraGeometriesValue.PushBack(extraGeometryValue, allocator); + } + value.AddMember("extraGeometries", extraGeometriesValue, allocator); + } orjson::SetJsonValueByKey(value, "isStatic", _bStatic, allocator); orjson::SetJsonValueByKey(value, "isEnabled", _bIsEnabled, allocator); @@ -337,26 +330,46 @@ void KinBody::LinkInfo::DeserializeJSON(const rapidjson::Value &value, dReal fUn } } - _mapExtraGeometries.clear(); - // if (value.HasMember("extraGeometries")) { - // for (rapidjson::Value::ConstMemberIterator it = value["extraGeometries"].MemberBegin(); it != value["extraGeometries"].MemberEnd(); ++it) { - // if (_mapExtraGeometries.find(it->name.GetString()) == _mapExtraGeometries.end()) { - // _mapExtraGeometries[it->name.GetString()] = std::vector(); - // } - // std::vector& vgeometries = _mapExtraGeometries[it->name.GetString()]; - // vgeometries.reserve(it->value.Size() + vgeometries.size()); - // size_t iGeometry = 0; - // for(rapidjson::Value::ConstValueIterator im = it->value.Begin(); im != it->value.End(); ++im, ++iGeometry) { - // std::string id = orjson::GetStringJsonValueByKey(*im, "id"); - // UpdateOrCreateInfoWithNameCheck(*im, id, vgeometries, "name", fUnitScale); - // } - // } - // } + if (value.HasMember("extraGeometries") && value["extraGeometries"].IsArray()) { + for (rapidjson::Value::ConstValueIterator it = value["extraGeometries"].Begin(); it != value["extraGeometries"].End(); ++it) { + std::string id; + // set id from id or name if exists, else throw error + if (value.HasMember("id")) { + orjson::LoadJsonValueByKey(value, "id", id); + } + else if (value.HasMember("name")) { + orjson::LoadJsonValueByKey(value, "name", id); + } + else { + RAVELOG_WARN_FORMAT("ignored an entry in extrageometries in link %s due to missing or empty id and name", this->_id); + continue; + } + + // deserialize if id or name is not empty + _DeserializeExtraGeometryInfo(id, *it, fUnitScale, options); + } + } orjson::LoadJsonValueByKey(value, "isStatic", _bStatic); orjson::LoadJsonValueByKey(value, "isEnabled", _bIsEnabled); orjson::LoadJsonValueByKey(value, "isSelfCollisionIgnored", _bIgnoreSelfCollision); } +void KinBody::LinkInfo::_DeserializeExtraGeometryInfo(const std::string& id, const rapidjson::Value& rExtraGeom, dReal fUnitScale, int options) { + std::map::iterator itExtraGeom = _mapExtraGeometries.find(id); + ExtraGeometryInfoPtr pInfo; + if (itExtraGeom != _mapExtraGeometries.end()) { + pInfo = itExtraGeom->second; + } + else { + _mapExtraGeometries[id] = ExtraGeometryInfoPtr(new ExtraGeometryInfo()); + pInfo = _mapExtraGeometries.at(id); + } + + // if geometry group exists, try update it, otherwise create one + if (!!pInfo) { + pInfo->DeserializeJSON(rExtraGeom, fUnitScale, options); + } +} void KinBody::LinkInfo::_DeserializeReadableInterface(const std::string& id, const rapidjson::Value& rReadable, dReal fUnitScale) { std::map::iterator itReadable = _mReadableInterfaces.find(id); @@ -789,18 +802,18 @@ void KinBody::Link::InitGeometries(std::list& geometries, _InitGeometriesInternal(bForceRecomputeMeshCollision); } -void KinBody::Link::SetGeometriesFromGroup(const std::string& groupname) +void KinBody::Link::SetGeometriesFromGroup(const std::string& groupid) { std::vector* pvinfos = NULL; - if( groupname.size() == 0 ) { + if( groupid.size() == 0 ) { pvinfos = &_info._vgeometryinfos; } else { - std::map< std::string, std::vector >::iterator it = _info._mapExtraGeometries.find(groupname); + std::map< std::string, KinBody::ExtraGeometryInfoPtr >::iterator it = _info._mapExtraGeometries.find(groupid); if( it == _info._mapExtraGeometries.end() ) { - throw OPENRAVE_EXCEPTION_FORMAT(_("could not find geometries %s for link %s"),groupname%GetName(),ORE_InvalidArguments); + throw OPENRAVE_EXCEPTION_FORMAT(_("could not find geometries %s for link %s"),groupid%GetName(),ORE_InvalidArguments); } - pvinfos = &it->second; + pvinfos = &it->second->_vgeometryinfos; } _vGeometries.resize(pvinfos->size()); for(size_t i = 0; i < pvinfos->size(); ++i) { @@ -813,20 +826,20 @@ void KinBody::Link::SetGeometriesFromGroup(const std::string& groupname) _Update(); } -const std::vector& KinBody::Link::GetGeometriesFromGroup(const std::string& groupname) const +const std::vector& KinBody::Link::GetGeometriesFromGroup(const std::string& groupid) const { - std::map< std::string, std::vector >::const_iterator it = _info._mapExtraGeometries.find(groupname); + std::map< std::string, KinBody::ExtraGeometryInfoPtr >::const_iterator it = _info._mapExtraGeometries.find(groupid); if( it == _info._mapExtraGeometries.end() ) { - std::stringstream ssGroupNames; - for(const std::pair< const std::string, std::vector >& grouppair : _info._mapExtraGeometries) { - ssGroupNames << grouppair.first << ", "; + std::stringstream ssgroupids; + for(const std::pair< const std::string, KinBody::ExtraGeometryInfoPtr >& grouppair : _info._mapExtraGeometries) { + ssgroupids << grouppair.first << ", "; } - throw OPENRAVE_EXCEPTION_FORMAT(_("env=%s, geometry group '%s' does not exist for body '%s' link '%s', current number of geometries=%d, extra groups=[%s], isEnabled=%d."), GetParent()->GetEnv()->GetNameId()%groupname%GetParent()->GetName()%GetName()%_vGeometries.size()%ssGroupNames.str()%_info._bIsEnabled, ORE_InvalidArguments); + throw OPENRAVE_EXCEPTION_FORMAT(_("env=%s, geometry group '%s' does not exist for body '%s' link '%s', current number of geometries=%d, extra groups=[%s], isEnabled=%d."), GetParent()->GetEnv()->GetNameId()%groupid%GetParent()->GetName()%GetName()%_vGeometries.size()%ssgroupids.str()%_info._bIsEnabled, ORE_InvalidArguments); } - return it->second; + return it->second->_vgeometryinfos; } -void KinBody::Link::_SetGroupGeometriesNoPostprocess(const std::string& groupname, const std::vector& geometries) +void KinBody::Link::_SetGroupGeometriesNoPostprocess(const std::string& groupid, const std::vector& geometries) { FOREACH(itgeominfo, geometries) { if (!(*itgeominfo)) { @@ -834,24 +847,27 @@ void KinBody::Link::_SetGroupGeometriesNoPostprocess(const std::string& groupnam throw OPENRAVE_EXCEPTION_FORMAT("GeometryInfo index %d is invalid for body %s", igeominfo % GetParent()->GetName(), ORE_InvalidArguments); } } - std::map>::iterator it = _info._mapExtraGeometries.insert(make_pair(groupname, std::vector())).first; - it->second.resize(geometries.size()); - std::copy(geometries.begin(), geometries.end(), it->second.begin()); + KinBody::ExtraGeometryInfoPtr newExtraGeom( new KinBody::ExtraGeometryInfo() ); + newExtraGeom->_id = groupid; + newExtraGeom->_name = groupid; + std::map::iterator it = _info._mapExtraGeometries.insert(make_pair(groupid, newExtraGeom)).first; + it->second->_vgeometryinfos.resize(geometries.size()); + std::copy(geometries.begin(), geometries.end(), it->second->_vgeometryinfos.begin()); } -void KinBody::Link::SetGroupGeometries(const std::string& groupname, const std::vector& geometries) +void KinBody::Link::SetGroupGeometries(const std::string& groupid, const std::vector& geometries) { - _SetGroupGeometriesNoPostprocess(groupname, geometries); + _SetGroupGeometriesNoPostprocess(groupid, geometries); GetParent()->_PostprocessChangedParameters(Prop_LinkGeometryGroup); // have to notify collision checkers that the geometry info they are caching could have changed. } -int KinBody::Link::GetGroupNumGeometries(const std::string& groupname) const +int KinBody::Link::GetGroupNumGeometries(const std::string& groupid) const { - std::map< std::string, std::vector >::const_iterator it = _info._mapExtraGeometries.find(groupname); + std::map< std::string, KinBody::ExtraGeometryInfoPtr >::const_iterator it = _info._mapExtraGeometries.find(groupid); if( it == _info._mapExtraGeometries.end() ) { return -1; } - return it->second.size(); + return it->second->_vgeometryinfos.size(); } void KinBody::Link::AddGeometry(KinBody::GeometryInfoPtr pginfo, bool addToGroups) @@ -876,7 +892,7 @@ void KinBody::Link::AddGeometry(KinBody::GeometryInfoPtr pginfo, bool addToGroup } if( addToGroups ) { FOREACH(itgeometrygroup, _info._mapExtraGeometries) { - FOREACH(itgeometryinfo, itgeometrygroup->second) { + FOREACH(itgeometryinfo, itgeometrygroup->second->_vgeometryinfos) { if( (*itgeometryinfo)->_name == ginfo._name ) { throw OPENRAVE_EXCEPTION_FORMAT(_("newly added geometry %s for group %s has conflicting name for link %s"), ginfo._name%itgeometrygroup->first%GetName(), ORE_InvalidArguments); } @@ -890,13 +906,13 @@ void KinBody::Link::AddGeometry(KinBody::GeometryInfoPtr pginfo, bool addToGroup _info._vgeometryinfos.push_back(pginfo); if( addToGroups ) { FOREACH(itgeometrygroup, _info._mapExtraGeometries) { - itgeometrygroup->second.push_back(pginfo); + itgeometrygroup->second->_vgeometryinfos.push_back(pginfo); } } _Update(true, Prop_LinkGeometryGroup); // have to notify collision checkers that the geometry info they are caching could have changed. } -void KinBody::Link::AddGeometryToGroup(KinBody::GeometryInfoPtr pginfo, const std::string& groupname) +void KinBody::Link::AddGeometryToGroup(KinBody::GeometryInfoPtr pginfo, const std::string& groupid) { if( !pginfo ) { throw OPENRAVE_EXCEPTION_FORMAT(_("tried to add improper geometry to link %s"), GetName(), ORE_InvalidArguments); @@ -904,19 +920,19 @@ void KinBody::Link::AddGeometryToGroup(KinBody::GeometryInfoPtr pginfo, const st const KinBody::GeometryInfo& ginfo = *pginfo; - std::map< std::string, std::vector >::iterator it = _info._mapExtraGeometries.find(groupname); + std::map< std::string, KinBody::ExtraGeometryInfoPtr >::iterator it = _info._mapExtraGeometries.find(groupid); if( it == _info._mapExtraGeometries.end() ) { - throw OPENRAVE_EXCEPTION_FORMAT(_("geometry group %s does not exist for link %s"), groupname%GetName(), ORE_InvalidArguments); + throw OPENRAVE_EXCEPTION_FORMAT(_("geometry group %s does not exist for link %s"), groupid%GetName(), ORE_InvalidArguments); } if( ginfo._name.size() > 0 ) { - FOREACHC(itgeometryinfo, it->second) { + FOREACHC(itgeometryinfo, it->second->_vgeometryinfos) { if( (*itgeometryinfo)->_name == ginfo._name ) { - throw OPENRAVE_EXCEPTION_FORMAT(_("newly added geometry %s for group %s has conflicting name for link %s"), ginfo._name%groupname%GetName(), ORE_InvalidArguments); + throw OPENRAVE_EXCEPTION_FORMAT(_("newly added geometry %s for group %s has conflicting name for link %s"), ginfo._name%groupid%GetName(), ORE_InvalidArguments); } } } - it->second.push_back(pginfo); + it->second->_vgeometryinfos.push_back(pginfo); _Update(true, Prop_LinkGeometryGroup); // have to notify collision checkers that the geometry info they are caching could have changed. } @@ -948,10 +964,10 @@ void KinBody::Link::RemoveGeometryByName(const std::string& geometryname, bool r if( removeFromAllGroups ) { FOREACH(itgeometrygroup, _info._mapExtraGeometries) { - std::vector::iterator itgeometryinfo2 = itgeometrygroup->second.begin(); - while(itgeometryinfo2 != itgeometrygroup->second.end()) { + std::vector::iterator itgeometryinfo2 = itgeometrygroup->second->_vgeometryinfos.begin(); + while(itgeometryinfo2 != itgeometrygroup->second->_vgeometryinfos.end()) { if( (*itgeometryinfo2)->_name == geometryname ) { - itgeometryinfo2 = itgeometrygroup->second.erase(itgeometryinfo2); + itgeometryinfo2 = itgeometrygroup->second->_vgeometryinfos.erase(itgeometryinfo2); bChanged = true; } else {