XMLSceneImporter.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package MemoryX::XMLSceneImporter
17 * @author (kozlov at kit dot edu)
18 * @date 2012
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22 
23 #include "XMLSceneImporter.h"
24 
27 
28 #include <fstream>
29 #include <filesystem>
30 
31 namespace fs = std::filesystem;
32 
33 namespace memoryx
34 {
36  {
37  usingProxy("WorkingMemory");
38  usingProxy("LongtermMemory");
39  }
40 
41 
43  {
44  ARMARX_INFO << "Starting XMLSceneImporter";
45 
46  memoryPrx = getProxy<WorkingMemoryInterfacePrx>("WorkingMemory");
47  objectInstancesMemoryPrx = memoryPrx->getObjectInstancesSegment();
48 
49  longtermMemoryPrx = getProxy<LongtermMemoryInterfacePrx>("LongtermMemory");
50 
51  const std::string sceneFile = getProperty<std::string>("SceneFile").getValue();
52  const std::string snapshotName = getProperty<std::string>("SnapshotName").getValue();
53  targetUnit = getProperty<LengthUnit>("TargetLengthUnit").getValue();
54 
55  importXMLSnapshot(sceneFile);
56 
57  if (longtermMemoryPrx->saveWorkingMemorySnapshot(snapshotName, memoryPrx))
58  {
59  ARMARX_INFO << "Snapshot " << snapshotName << " saved. Import complete!";
60  }
61  }
62 
63  void XMLSceneImporter::importXMLSnapshot(const std::string& fileName)
64  {
65  fs::path fpath(fileName);
66 
67  if (!fs::exists(fpath))
68  {
69  ARMARX_ERROR << "File " << fileName << " does not exist! Aborting.";
70  return;
71  }
72 
73  std::ifstream infile(fpath.c_str());
74  std::string XMLString((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());
75 
76  // parse the specified scene file
78 
79  try
80  {
81  XMLDoc.parse<0>(const_cast<char*>(XMLString.c_str()));
82  }
83  catch (rapidxml::parse_error& e)
84  {
85  ARMARX_ERROR << "Error parsing XML file: " << e.what();
86  return;
87  }
88 
89  // check if it contains a toplevel <scene> tag
90  rapidxml::xml_node<>* rootNode = XMLDoc.first_node("scene");
91 
92  if (!rootNode)
93  {
94  ARMARX_ERROR << "Malformed XML-file: <scene> Tag is missing";
95  return;
96  }
97 
98  // the next child tag must be <nodes>
99  rapidxml::xml_node<>* sceneNodes = rootNode->first_node("nodes");
100 
101  if (!sceneNodes)
102  {
103  ARMARX_ERROR << "Malformed XML-file: <scene> must be followed by a <nodes> tag.";
104  return;
105  }
106 
107  // iterate over all <node> tags and import them into the objectInstance memory
108  for (rapidxml::xml_node<>* entityNode = sceneNodes->first_node("node"); entityNode; entityNode = entityNode->next_sibling("node"))
109  {
110  const ObjectInstanceBasePtr newObjectInstance = createObjectInstanceFromXML(entityNode);
111 
112  if (newObjectInstance)
113  {
114  objectInstancesMemoryPrx->addEntity(newObjectInstance);
115  }
116  }
117 
118  ARMARX_INFO << "File successfully imported: " << fileName;
119  }
120 
121 
122  ObjectInstanceBasePtr XMLSceneImporter::createObjectInstanceFromXML(rapidxml::xml_node<>* xmlNode)
123  {
124  if (!xmlNode)
125  {
126  return ObjectInstancePtr();
127  }
128 
129  const std::string name(xmlNode->first_attribute("name")->value());
130 
131  ObjectInstancePtr objectInstance = new ObjectInstance(name);
132  objectInstance->setExistenceCertainty(1.0f);
133 
134  // assume object class = object name for now
135  objectInstance->setClass(name, 1.0f);
136 
137  // load position
138  armarx::FramedPositionBasePtr entityPosition = positionFromXML(xmlNode);
139 
140  if (!entityPosition)
141  {
142  ARMARX_ERROR << "<position> tag is missing in node " << name;
143  return ObjectInstancePtr();
144  }
145 
146  objectInstance->setPosition(entityPosition);
147 
148  // load rotation
149  armarx::FramedOrientationBasePtr entityOrientation = orientationFromXML(xmlNode);
150 
151  if (entityOrientation)
152  {
153  objectInstance->setOrientation(entityOrientation);
154  }
155 
156  return objectInstance;
157  }
158 
159  armarx::FramedPositionBasePtr XMLSceneImporter::positionFromXML(rapidxml::xml_node<>* xmlNode)
160  {
161  rapidxml::xml_node<>* positionNode = xmlNode->first_node("position");
162 
163  if (!positionNode)
164  {
165  return armarx::FramedPositionPtr();
166  }
167 
168  Eigen::Vector3f position;
169  std::istringstream(positionNode->first_attribute("x")->value()) >> position[0];
170  std::istringstream(positionNode->first_attribute("y")->value()) >> position[1];
171  std::istringstream(positionNode->first_attribute("z")->value()) >> position[2];
172 
173  float scaleFactor = scaleFactorFromPositionXML(positionNode);
174  position *= scaleFactor;
175 
176  return new armarx::FramedPosition(position, armarx::GlobalFrame, "");
177  }
178 
179  armarx::FramedOrientationBasePtr XMLSceneImporter::orientationFromXML(rapidxml::xml_node<>* xmlNode)
180  {
181  rapidxml::xml_node<>* quaternion = xmlNode->first_node("rotation");
182 
183  if (!quaternion)
184  {
186  }
187 
188  Eigen::Quaternionf orientation;
189  std::istringstream(quaternion->first_attribute("qx")->value()) >> orientation.x();
190  std::istringstream(quaternion->first_attribute("qy")->value()) >> orientation.y();
191  std::istringstream(quaternion->first_attribute("qz")->value()) >> orientation.z();
192  std::istringstream(quaternion->first_attribute("qw")->value()) >> orientation.w();
193 
194  return new armarx::FramedOrientation(orientation.toRotationMatrix(), armarx::GlobalFrame, "");
195  }
196 
197  float XMLSceneImporter::scaleFactorFromPositionXML(rapidxml::xml_node<>* positionNode)
198  {
199  std::string unitstring = "METER"; // assume meter if no <unit> tag is available
200 
201  rapidxml::xml_attribute<char>* unitAttribute = positionNode->first_attribute("unit");
202 
203  if (unitAttribute)
204  {
205  unitstring = std::string(unitAttribute->value());
206  }
207 
208  float sourceFactor;
209 
210  if (unitstring == "METER")
211  {
212  sourceFactor = 1.f;
213  }
214 
215  if (unitstring == "CENTIMETER")
216  {
217  sourceFactor = 100.f;
218  }
219  else if (unitstring == "MILLIMETER")
220  {
221  sourceFactor = 1000.f;
222  }
223  else
224  {
225  std::stringstream strstr;
226  strstr << __FILE__ << " : " << __LINE__ << " (" << __FUNCTION__ << "): unknown unitstring '" << unitstring << "'";
227  throw std::invalid_argument {strstr.str()};
228  }
229 
230  float targetFactor;
231 
232  switch (targetUnit)
233  {
234  case eMETER:
235  targetFactor = 1.f;
236  break;
237 
238  case eCENTIMETER:
239  targetFactor = 100.f;
240  break;
241 
242  case eMILLIMETER:
243  targetFactor = 1000.f;
244  break;
245  default:
246  std::stringstream strstr;
247  strstr << __FILE__ << " : " << __LINE__ << " (" << __FUNCTION__ << "): unknown targetUnit '" << targetUnit << "'";
248  throw std::invalid_argument {strstr.str()};
249  }
250 
251  return targetFactor / sourceFactor;
252  }
253 
254 }
rapidxml::parse_error::what
const char * what() const noexcept override
Gets human readable description of error.
Definition: rapidxml.hpp:86
rapidxml::xml_node::next_sibling
xml_node< Ch > * next_sibling(const Ch *name=nullptr, std::size_t name_size=0, bool case_sensitive=true) const
Gets next sibling node, optionally matching node name.
Definition: rapidxml.hpp:1121
JSONObject.h
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:62
memoryx
VirtualRobot headers.
Definition: CommonPlacesTester.cpp:48
memoryx::eCENTIMETER
@ eCENTIMETER
Definition: XMLSceneImporter.h:38
rapidxml::xml_node::first_attribute
xml_attribute< Ch > * first_attribute(const Ch *name=nullptr, std::size_t name_size=0, bool case_sensitive=true) const
Gets first attribute of node, optionally matching attribute name.
Definition: rapidxml.hpp:1151
memoryx::XMLSceneImporter::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: XMLSceneImporter.cpp:42
memoryx::eMILLIMETER
@ eMILLIMETER
Definition: XMLSceneImporter.h:39
rapidxml::xml_attribute< char >
memoryx::XMLSceneImporter::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: XMLSceneImporter.cpp:35
XMLSceneImporter.h
memoryx::ObjectInstancePtr
IceInternal::Handle< ObjectInstance > ObjectInstancePtr
Definition: ObjectInstance.h:42
armarx::FramedPositionPtr
IceInternal::Handle< FramedPosition > FramedPositionPtr
Definition: FramedPose.h:134
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
rapidxml::xml_node::first_node
xml_node< Ch > * first_node(const Ch *name=nullptr, std::size_t name_size=0, bool case_sensitive=true) const
Gets first child node, optionally matching node name.
Definition: rapidxml.hpp:1027
rapidxml::xml_document
This class represents root of the DOM hierarchy.
Definition: rapidxml.hpp:140
rapidxml::xml_node
Class representing a node of XML document.
Definition: rapidxml.hpp:138
armarx::FramedOrientationPtr
IceInternal::Handle< FramedOrientation > FramedOrientationPtr
Definition: FramedPose.h:191
ObjectInstance.h
armarx::VariantType::FramedOrientation
const VariantTypeId FramedOrientation
Definition: FramedPose.h:40
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::Quaternion< float, 0 >
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:39
memoryx::eMETER
@ eMETER
Definition: XMLSceneImporter.h:37
rapidxml::xml_document::parse
void parse(Ch *text)
Parses zero-terminated XML string according to given flags.
Definition: rapidxml.hpp:1575
rapidxml::parse_error
Parse error exception.
Definition: rapidxml.hpp:72
armarx::ManagedIceObject::usingProxy
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Definition: ManagedIceObject.cpp:151