Newer
Older

Fabian Reister
committed
#include "VirtualRobot.h"
#include "../Visualization/TriMeshModel.h"
#include <iostream>
using namespace std;
VirtualRobot::ObstaclePtr ObjectIO::loadObstacle(const std::string& xmlFile)
{
// load file
std::ifstream in(xmlFile.c_str());
THROW_VR_EXCEPTION_IF(!in.is_open(), "Could not open XML file:" << xmlFile);
std::filesystem::path filenameBaseComplete(xmlFile);
std::filesystem::path filenameBasePath = filenameBaseComplete.parent_path();
std::string basePath = filenameBasePath.string();
VirtualRobot::ObstaclePtr res = loadObstacle(in, basePath);
THROW_VR_EXCEPTION_IF(!res, "Error while parsing file " << xmlFile);
res->setFilename(xmlFile);
return res;
}
VirtualRobot::ObstaclePtr ObjectIO::loadObstacle(const std::ifstream& xmlFile, const std::string& basePath /*= ""*/)
{
// load file
THROW_VR_EXCEPTION_IF(!xmlFile.is_open(), "Could not open XML file");
std::stringstream buffer;
buffer << xmlFile.rdbuf();
std::string objectXML(buffer.str());
VirtualRobot::ObstaclePtr res = createObstacleFromString(objectXML, basePath);
THROW_VR_EXCEPTION_IF(!res, "Error while parsing file.");
return res;
}
VirtualRobot::ManipulationObjectPtr ObjectIO::loadManipulationObject(const std::string& xmlFile)
{
// load file
std::ifstream in(xmlFile.c_str());
THROW_VR_EXCEPTION_IF(!in.is_open(), "Could not open XML file:" << xmlFile);
std::filesystem::path filenameBaseComplete(xmlFile);
std::filesystem::path filenameBasePath = filenameBaseComplete.parent_path();
std::string basePath = filenameBasePath.string();
VirtualRobot::ManipulationObjectPtr res = loadManipulationObject(in, basePath);
THROW_VR_EXCEPTION_IF(!res, "Error while parsing file " << xmlFile);
res->setFilename(xmlFile);
return res;
}
VirtualRobot::ManipulationObjectPtr ObjectIO::loadManipulationObject(const std::ifstream& xmlFile, const std::string& basePath /*= ""*/)
{
// load file
THROW_VR_EXCEPTION_IF(!xmlFile.is_open(), "Could not open XML file");
std::stringstream buffer;
buffer << xmlFile.rdbuf();
std::string objectXML(buffer.str());
VirtualRobot::ManipulationObjectPtr res = createManipulationObjectFromString(objectXML, basePath);
vahrenkamp
committed
res->initialize();
THROW_VR_EXCEPTION_IF(!res, "Error while parsing file.");
return res;
}
bool ObjectIO::writeSTL(TriMeshModelPtr t, const std::string& filename, const std::string& objectName, float scaling)
VR_ERROR << "Wrong input" << std::endl;
return false;
}
ofstream of;
VR_ERROR << "Could not open " << filename << " for writing" << std::endl;
return false;
}
of << "solid " << objectName << std::endl;
{
MathTools::TriangleFace& face = t->faces.at(i);
auto& p1 = t->vertices.at(face.id1);
auto& p2 = t->vertices.at(face.id2);
auto& p3 = t->vertices.at(face.id3);
auto normal1 = face.idNormal1 < t->normals.size() ? t->normals.at(face.idNormal1) : face.normal;
auto normal2 = face.idNormal2 < t->normals.size() ? t->normals.at(face.idNormal2) : face.normal;
auto normal3 = face.idNormal3 < t->normals.size() ? t->normals.at(face.idNormal3) : face.normal;
Eigen::Vector3f n = normal1 + normal2 + normal3;
n.normalize();
//Point p = h->vertex()->point();
//Point q = h->next()->vertex()->point();
//Point r = h->next()->next()->vertex()->point();
// compute normal
//Vector n = CGAL::cross_product( q-p, r-p);
//Vector norm = n / std::sqrt( n * n);
of << " facet normal " << n(0) << " " << n(1) << " " << n(2) << std::endl;
of << " outer loop " << std::endl;
of << " vertex " << p1(0)*scaling << " " << p1(1)*scaling << " " << p1(2)*scaling << std::endl;
of << " vertex " << p2(0)*scaling << " " << p2(1)*scaling << " " << p2(2)*scaling << std::endl;
of << " vertex " << p3(0)*scaling << " " << p3(1)*scaling << " " << p3(2)*scaling << std::endl;
of << " endloop " << std::endl;
of << " endfacet " << std::endl;
of << "endsolid " << objectName << std::endl;
of.close();
return true;
}
ObstaclePtr ObjectIO::processObstacle(rapidxml::xml_node<char>* objectXMLNode, const std::string& basePath)
THROW_VR_EXCEPTION_IF(!objectXMLNode, "No <Obstacle> tag in XML definition");
bool visuProcessed = false;
bool colProcessed = false;
VisualizationNodePtr visualizationNode;
CollisionModelPtr collisionModel;
bool useAsColModel = false;
SceneObject::Physics physics;
bool physicsDefined = false;
Eigen::Matrix4f globalPose = Eigen::Matrix4f::Identity();
SceneObject::PrimitiveApproximation primitiveApproximation;
// get name
std::string objName = processNameAttribute(objectXMLNode);

Fabian Reister
committed
// update global pose
rapidxml::xml_node<>* poseNode = objectXMLNode->first_node("globalpose", 0, false);
if (poseNode != nullptr)
{
processTransformNode(poseNode, objName, globalPose);
}
// Check if there is an xml file to load
rapidxml::xml_node<>* xmlFileNode = objectXMLNode->first_node("file", 0, false);
if (xmlFileNode)
{
std::string xmlFile = processFileNode(xmlFileNode, basePath);
ObstaclePtr result = loadObstacle(xmlFile);
if (!result)
{
return result;
}
if (!objName.empty())
{
result->setName(objName);
}

Fabian Reister
committed
// update global pose
result->setGlobalPose(globalPose);
THROW_VR_EXCEPTION_IF(objName.empty(), "Obstacle definition expects attribute 'name'");
rapidxml::xml_node<>* node = objectXMLNode->first_node();
while (node)
{
std::string nodeName = getLowerCase(node->name());
if (nodeName == "visualization")
{
THROW_VR_EXCEPTION_IF(visuProcessed, "Two visualization tags defined in Obstacle '" << objName << "'." << endl);
visualizationNode = processVisualizationTag(node, objName, basePath, useAsColModel);
visuProcessed = true;
if (useAsColModel)
{
THROW_VR_EXCEPTION_IF(colProcessed, "Two collision tags defined in Obstacle '" << objName << "'." << endl);
std::string colModelName = objName;
colModelName += "_VISU_ColModel";
// todo: ID?
collisionModel.reset(new CollisionModel(visualizationNode, colModelName, CollisionCheckerPtr()));
colProcessed = true;
}
}
else if (nodeName == "collisionmodel")
{
THROW_VR_EXCEPTION_IF(colProcessed, "Two collision tags defined in Obstacle '" << objName << "'." << endl);
collisionModel = processCollisionTag(node, objName, basePath);
colProcessed = true;
}
else if (nodeName == "primitivemodel")
{
processPrimitiveModelTag(primitiveApproximation, node);
}
else if (nodeName == "physics")
{
THROW_VR_EXCEPTION_IF(physicsDefined, "Two physics tags defined in Obstacle '" << objName << "'." << endl);
processPhysicsTag(node, objName, physics);
physicsDefined = true;
}
else if (nodeName == "globalpose")
{
processTransformNode(node, objName, globalPose);
}
else
{
THROW_VR_EXCEPTION("XML definition <" << nodeName << "> not supported in Obstacle <" << objName << ">." << endl);
}
node = node->next_sibling();
}
// build object
ObstaclePtr object(new Obstacle(objName, visualizationNode, collisionModel, physics));
object->setGlobalPose(globalPose);
object->setPrimitiveApproximation(primitiveApproximation);
VirtualRobot::ManipulationObjectPtr ObjectIO::createManipulationObjectFromString(const std::string& xmlString, const std::string& basePath /*= ""*/)
{
// copy string content to char array
std::vector<char> y(xmlString.size() + 1);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
strncpy(y.data(), xmlString.c_str(), xmlString.size() + 1);
#pragma GCC diagnostic pop
VirtualRobot::ManipulationObjectPtr obj;
rapidxml::xml_document<char> doc; // character type defaults to char
doc.parse<0>(y.data()); // 0 means default parse flags
rapidxml::xml_node<char>* objectXMLNode = doc.first_node("ManipulationObject");
obj = processManipulationObject(objectXMLNode, basePath);
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
}
catch (rapidxml::parse_error& e)
{
THROW_VR_EXCEPTION("Could not parse data in xml definition" << endl
<< "Error message:" << e.what() << endl
<< "Position: " << endl << e.where<char>() << endl);
return ManipulationObjectPtr();
}
catch (VirtualRobot::VirtualRobotException&)
{
// rethrow the current exception
throw;
}
catch (std::exception& e)
{
THROW_VR_EXCEPTION("Error while parsing xml definition" << endl
<< "Error code:" << e.what() << endl);
return ManipulationObjectPtr();
}
catch (...)
{
THROW_VR_EXCEPTION("Error while parsing xml definition" << endl);
return ManipulationObjectPtr();
}
return obj;
ManipulationObjectPtr ObjectIO::processManipulationObject(rapidxml::xml_node<char>* objectXMLNode, const std::string& basePath)
THROW_VR_EXCEPTION_IF(!objectXMLNode, "No <ManipulationObject> tag in XML definition");
bool visuProcessed = false;
bool colProcessed = false;
VisualizationNodePtr visualizationNode;
CollisionModelPtr collisionModel;
bool useAsColModel = false;
SceneObject::Physics physics;
bool physicsDefined = false;
Eigen::Matrix4f globalPose = Eigen::Matrix4f::Identity();
std::vector< rapidxml::xml_node<>* > sensorTags;
SceneObject::PrimitiveApproximation primitiveApproximation;
// get name
std::string objName = processNameAttribute(objectXMLNode);
// first check if there is an xml file to load
rapidxml::xml_node<>* xmlFileNode = objectXMLNode->first_node("file", 0, false);
if (xmlFileNode)
{
std::string xmlFile = processFileNode(xmlFileNode, basePath);
ManipulationObjectPtr result = loadManipulationObject(xmlFile);
if (!result)
{
return result;
}
if (!objName.empty())
{
result->setName(objName);
}
// update global pose
rapidxml::xml_node<>* poseNode = objectXMLNode->first_node("globalpose", 0, false);
if (poseNode)
{
processTransformNode(poseNode, objName, globalPose);
result->setGlobalPose(globalPose);
}
return result;
}
THROW_VR_EXCEPTION_IF(objName.empty(), "ManipulationObject definition expects attribute 'name'");
rapidxml::xml_node<>* node = objectXMLNode->first_node();
while (node)
{
std::string nodeName = getLowerCase(node->name());
if (nodeName == "visualization")
{
THROW_VR_EXCEPTION_IF(visuProcessed, "Two visualization tags defined in ManipulationObject '" << objName << "'." << endl);
visualizationNode = processVisualizationTag(node, objName, basePath, useAsColModel);
visuProcessed = true;
if (useAsColModel)
{
THROW_VR_EXCEPTION_IF(colProcessed, "Two collision tags defined in ManipulationObject '" << objName << "'." << endl);
std::string colModelName = objName;
colModelName += "_VISU_ColModel";
// todo: ID?
collisionModel.reset(new CollisionModel(visualizationNode, colModelName, CollisionCheckerPtr()));
colProcessed = true;
}
}
else if (nodeName == "collisionmodel")
{
THROW_VR_EXCEPTION_IF(colProcessed, "Two collision tags defined in ManipulationObject '" << objName << "'." << endl);
collisionModel = processCollisionTag(node, objName, basePath);
colProcessed = true;
}
else if (nodeName == "primitivemodel")
{
processPrimitiveModelTag(primitiveApproximation, node);
}
else if (nodeName == "physics")
{
THROW_VR_EXCEPTION_IF(physicsDefined, "Two physics tags defined in ManipulationObject '" << objName << "'." << endl);
processPhysicsTag(node, objName, physics);
physicsDefined = true;
}
else if (nodeName == "graspset")
{
GraspSetPtr gs = processGraspSet(node, objName);
THROW_VR_EXCEPTION_IF(!gs, "Invalid grasp set in '" << objName << "'." << endl);
graspSets.push_back(gs);
}
else if (nodeName == "sensor")
{
sensorTags.push_back(node);
}
else if (nodeName == "globalpose")
{
processTransformNode(node, objName, globalPose);
}
else
{
THROW_VR_EXCEPTION("XML definition <" << nodeName << "> not supported in ManipulationObject <" << objName << ">." << endl);
}
node = node->next_sibling();
}
// build object
ManipulationObjectPtr object(new ManipulationObject(objName, visualizationNode, collisionModel, physics));
// process sensors
for (auto& sensorTag : sensorTags)
processSensor(object, sensorTag, RobotDescription::eFull, basePath);
for (const auto& graspSet : graspSets)
object->setPrimitiveApproximation(primitiveApproximation);
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
VirtualRobot::ObstaclePtr ObjectIO::createObstacleFromString(const std::string& xmlString, const std::string& basePath /*= ""*/)
{
// copy string content to char array
char* y = new char[xmlString.size() + 1];
strncpy(y, xmlString.c_str(), xmlString.size() + 1);
VirtualRobot::ObstaclePtr obj;
try
{
rapidxml::xml_document<char> doc; // character type defaults to char
doc.parse<0>(y); // 0 means default parse flags
rapidxml::xml_node<char>* objectXMLNode = doc.first_node("Obstacle");
obj = processObstacle(objectXMLNode, basePath);
}
catch (rapidxml::parse_error& e)
{
delete[] y;
THROW_VR_EXCEPTION("Could not parse data in xml definition" << endl
<< "Error message:" << e.what() << endl
<< "Position: " << endl << e.where<char>() << endl);
return ObstaclePtr();
}
catch (VirtualRobot::VirtualRobotException&)
{
// rethrow the current exception
delete[] y;
throw;
}
catch (std::exception& e)
{
delete[] y;
THROW_VR_EXCEPTION("Error while parsing xml definition" << endl
<< "Error code:" << e.what() << endl);
return ObstaclePtr();
}
catch (...)
{
delete[] y;
THROW_VR_EXCEPTION("Error while parsing xml definition" << endl);
return ObstaclePtr();
}
delete[] y;
return obj;
}
bool ObjectIO::saveManipulationObject(ManipulationObjectPtr object, const std::string& xmlFile)
{
THROW_VR_EXCEPTION_IF(!object, "NULL object");
std::filesystem::path filenameBaseComplete(xmlFile);
std::filesystem::path filenameBasePath = filenameBaseComplete.parent_path();
std::string basePath = filenameBasePath.string();
std::string xmlString = object->toXML(basePath);
// save file
return BaseIO::writeXMLFile(xmlFile, xmlString, true);
}