8 #include <ros/console.h>
10 #include <geometry_msgs/Pose.h>
12 #include <moveit_msgs/CollisionObject.h>
14 #include <geometric_shapes/shape_operations.h>
28 struct SceneParsingContext
41 tinyxml2::XMLElement *getFirstChild(T *elem,
const std::string &name =
"")
43 tinyxml2::XMLHandle handle(elem);
44 tinyxml2::XMLElement *child;
46 child = handle.FirstChildElement().ToElement();
48 child = handle.FirstChildElement(name.c_str()).ToElement();
53 RobotPose TFfromXML(tinyxml2::XMLElement *transElem, tinyxml2::XMLElement *rotationElem,
54 tinyxml2::XMLElement *quatElem)
59 auto trans = IO::tokenize<double>(
std::string(transElem->GetText()));
60 tf.translation() = Eigen::Vector3d(trans[0], trans[1], trans[2]);
65 auto rot = IO::tokenize<double>(
std::string(rotationElem->GetText()));
67 Eigen::Vector3d axis(rot[0], rot[1], rot[2]);
70 tf.linear() = Eigen::AngleAxisd(
toRadians(rot[3]), axis).toRotationMatrix();
75 auto quat = IO::tokenize<double>(
std::string(quatElem->GetText()));
77 Eigen::Quaterniond q(quat[0], quat[1], quat[2], quat[3]);
80 tf.linear() = q.toRotationMatrix();
86 bool parseKinbody(SceneParsingContext &load_struct, tinyxml2::XMLElement *elem,
const RobotPose &tf,
91 RBX_ERROR(
"Ran into element that does not exist!");
95 auto *trans_elem = getFirstChild(elem,
"Translation");
96 auto *rot_elem = getFirstChild(elem,
"Rotation");
97 RobotPose this_tf = TFfromXML(trans_elem, rot_elem,
nullptr);
99 const char *filename = elem->Attribute(
"file");
104 tinyxml2::XMLDocument doc;
105 if (!doc.LoadFile(full_path.
c_str()))
107 RBX_ERROR(
"Cannot load file %s", full_path);
112 return parseKinbody(load_struct, getFirstChild(&doc,
"KinBody"), tf * this_tf,
planning_scene);
115 tinyxml2::XMLElement *body_elem = getFirstChild(elem);
116 for (; body_elem; body_elem = body_elem->NextSiblingElement())
120 moveit_msgs::CollisionObject coll_obj;
121 coll_obj.id = body_elem->Attribute(
"name");
122 coll_obj.header.frame_id =
"world";
124 tinyxml2::XMLElement *geom = getFirstChild(body_elem,
"Geom");
127 RBX_ERROR(
"Malformed File: No Geom attribute?");
134 TFfromXML(getFirstChild(geom,
"translation"),
nullptr, getFirstChild(geom,
"quat"));
139 const char *geom_type = geom->Attribute(
"type");
142 RBX_ERROR(
"Malformed File: No type attribute in geom element");
149 if (geom_str ==
"trimesh")
152 Eigen::Vector3d dimensions{1, 1, 1};
154 tinyxml2::XMLElement *data = getFirstChild(geom,
"Data");
158 load_struct.directory_stack.top() +
"/" +
std::string(data->GetText());
162 tinyxml2::XMLElement *render = getFirstChild(geom,
"Render");
165 load_struct.directory_stack.top() +
"/" +
std::string(data->GetText());
168 RBX_ERROR(
"Malformed File: No Data or Render Elements inside a trimesh Geom.");
174 coll_obj.meshes.push_back(mesh->getMeshMsg());
175 coll_obj.mesh_poses.push_back(pose_msg);
178 if (geom_str ==
"box")
180 tinyxml2::XMLElement *extents_elem = getFirstChild(geom,
"extents_elem");
181 if (not extents_elem)
183 RBX_ERROR(
"Malformed File: No extents_elem in a box geometry.");
187 auto extents = IO::tokenize<double>(extents_elem->GetText());
188 shapes::Shape *shape =
189 new shapes::Box(extents[0] * 2.0, extents[1] * 2.0, extents[2] * 2.0);
190 shapes::ShapeMsg msg;
191 shapes::constructMsgFromShape(shape, msg);
192 coll_obj.primitives.push_back(boost::get<shape_msgs::SolidPrimitive>(msg));
193 coll_obj.primitive_poses.push_back(pose_msg);
196 coll_obj.operation = moveit_msgs::CollisionObject::ADD;
198 load_struct.coll_objects.push_back(coll_obj);
203 load_struct.directory_stack.pop();
211 SceneParsingContext load_struct;
212 load_struct.directory_stack.push(model_dir);
216 tf.translation() = Eigen::Vector3d(0.0, 0.0, -0.346);
217 tf.linear() = Eigen::Quaterniond::Identity().toRotationMatrix();
218 load_struct.robot_offset = tf;
220 tinyxml2::XMLDocument doc;
227 auto *env = getFirstChild(&doc,
"Environment");
228 auto *
robot = getFirstChild(env,
"Robot");
230 load_struct.robot_offset =
231 load_struct.robot_offset * TFfromXML(getFirstChild(
robot,
"Translation"),
232 getFirstChild(
robot,
"RotationAxis"),
nullptr);
234 auto *elem = getFirstChild(env);
237 RBX_ERROR(
"There is no/an empty environment element in this openrave scene.");
241 for (; elem; elem = elem->NextSiblingElement())
244 if (p_key ==
"KinBody")
246 if (!parseKinbody(load_struct, elem, load_struct.robot_offset.inverse(),
planning_scene))
250 RBX_INFO(
"Ignoring elements of value %s", p_key);
253 if (not load_struct.coll_objects.empty())
static GeometryPtr makeMesh(const std::string &resource, const Eigen::Vector3d &scale={1, 1, 1})
Create a mesh from resource file.
#define RBX_ERROR(fmt,...)
Output a error logging message.
#define RBX_INFO(fmt,...)
Output a info logging message.
Functions for loading and animating robots in Blender.
std::string resolveParent(const std::string &path)
Resolves package:// URLs to get the directory this path is in.
std::string resolvePath(const std::string &path)
Resolves package:// URLs and relative file paths to their canonical form.
double toRadians(double v)
Convert an angle to radians.
geometry_msgs::Pose poseEigenToMsg(const RobotPose &pose)
Converts an RobotPose to a pose message.
bool fromXMLFile(moveit_msgs::PlanningScene &planning_scene, const std::string &file, const std::string &model_dir)
Loads a planning_scene from an OpenRAVE Environment XML.
Main namespace. Contains all library classes and functions.
std::decay< decltype(std::declval< moveit::core::Transforms >().getTransform("")) >::type RobotPose
A pose (point in SE(3)) used in various functions. Defined from what MoveIt! uses.