SimoxSceneImporter.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::SimoxSceneImporter
17 * @author (vahrenkamp at kit dot edu)
18 * @date 2013
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22 #define BOOST_NO_SCOPED_ENUMS
23 #define BOOST_NO_CXX11_SCOPED_ENUMS
24 #include "SimoxSceneImporter.h"
25 
30 
32 
34 
35 #include <VirtualRobot/XML/BaseIO.h>
36 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
37 #include <VirtualRobot/Visualization/VisualizationNode.h>
38 
39 #include <SimoxUtility/algorithm/string/string_tools.h>
40 
41 #include <Inventor/lists/SbStringList.h>
42 
43 #include <fstream>
44 #include <filesystem>
45 
46 
47 namespace fs = std::filesystem;
48 
49 using namespace VirtualRobot;
50 
51 namespace memoryx
52 {
53  SimoxSceneImporter::SimoxSceneImporter() :
54  TEMPDIR("simoxsceneimport__tmp"),
55  LONGTERM_SNAPSHOT_PREFIX("Snapshot_")
56  {
57  }
58 
60  {
61  usingProxy("WorkingMemory");
62  usingProxy("LongtermMemory");
63  usingProxy("PriorKnowledge");
64  usingProxy("CommonStorage");
65  }
66 
67 
69  {
70  ARMARX_INFO << "Starting SimoxSceneImporter";
71 
72  filesDBName = getProperty<std::string>("FilesDbName").getValue();
73  sceneFile = getProperty<std::string>("SceneFile").getValue();
74  snapshotName = getProperty<std::string>("SnapshotName").getValue();
75 
76  dbSerializer = new MongoSerializer(getIceManager()->getCommunicator(), true);
77 
78  dataBasePrx = getProxy<CommonStorageInterfacePrx>("CommonStorage");
79 
80  longtermMemoryPrx = getProxy<LongtermMemoryInterfacePrx>("LongtermMemory");
81 
82  memoryPrx = getProxy<WorkingMemoryInterfacePrx>("WorkingMemory");
83  objectInstancesMemoryPrx = memoryPrx->getObjectInstancesSegment(); // Fails if WorkingMemory.UsePriorKnowledge = false
84 
85  priorKnowledgePrx = getProxy<PriorKnowledgeInterfacePrx>("PriorKnowledge");
86  classesSegmentPrx = priorKnowledgePrx->getObjectClassesSegment();
87 
88 
89 
90  ScenePtr scene = loadSceneFromXML(sceneFile);
91 
92  if (!scene)
93  {
94  ARMARX_ERROR << "Error loading file " << sceneFile << " Aborting.";
95  return;
96  }
97 
98  memoryPrx->clear();
99 
100  if (!importScene(scene))
101  {
102  ARMARX_ERROR << "Error importing " << sceneFile << " Aborting.";
103  return;
104  }
105 
106  std::string prefixedSnapshotName = snapshotName;
107 
108  // check name
109  if (!simox::alg::starts_with(prefixedSnapshotName, SimoxSceneImporter::LONGTERM_SNAPSHOT_PREFIX))
110  {
111  prefixedSnapshotName = std::string(SimoxSceneImporter::LONGTERM_SNAPSHOT_PREFIX) + snapshotName;
112  ARMARX_WARNING << "Snapshot name must start with <" << SimoxSceneImporter::LONGTERM_SNAPSHOT_PREFIX << ">. Changing to " << prefixedSnapshotName;
113  }
114 
115  if (longtermMemoryPrx->saveWorkingMemorySnapshot(prefixedSnapshotName, memoryPrx))
116  {
117  ARMARX_INFO << "Snapshot " << prefixedSnapshotName << " saved. Import complete!";
118  }
119  }
120 
121  VirtualRobot::ScenePtr SimoxSceneImporter::loadSceneFromXML(const std::string& fileName)
122  {
123  fs::path fpath(fileName);
124 
125  if (!fs::exists(fpath))
126  {
127  ARMARX_ERROR << "File " << fileName << " does not exist! Aborting.";
128  return ScenePtr();
129  }
130 
131  ScenePtr scene;
132 
133  try
134  {
135  scene = SceneIO::loadScene(fileName);
136  }
137  catch (VirtualRobotException& e)
138  {
139  ARMARX_ERROR << "Could not load " << fileName << "\n\t" << e.what();
140  return ScenePtr();
141  }
142 
143  return scene;
144  }
145 
146 
147  bool SimoxSceneImporter::importScene(VirtualRobot::ScenePtr scene)
148  {
149  if (!scene || !objectInstancesMemoryPrx)
150  {
151  return false;
152  }
153 
154  // create temp directory
155  std::string prefixedSnapshotName = std::string(memoryx::PRIOR_COLLECTION_PREFIX) + snapshotName;
156  fs::path tmpImportDirectory = fs::path(SimoxSceneImporter::TEMPDIR) / fs::path(prefixedSnapshotName);
157 
158  fs::remove_all(tmpImportDirectory);
159  fs::create_directories(tmpImportDirectory);
160 
161  // copy all scene files into the temp directory
162  VirtualRobot::ScenePtr tmpScene = createTempScene(tmpImportDirectory.string(), scene);
163 
164  if (!tmpScene)
165  {
166  return false;
167  }
168 
169  // warn about robots in the scene
170  // the tmpScene should not have any robots any more
171  size_t robotCount = scene->getRobots().size();
172 
173  if (robotCount > 0)
174  {
175  ARMARX_WARNING << "Skipping " << robotCount << " robot defintions in scene file. Robots are not processed!";
176  }
177 
178  // process Obstacle and ManipulationObject instances
179  std::map<VirtualRobot::ObstaclePtr, ObjectInstanceBasePtr> objectInstances;
180  // Obstacles
181  int objectInstanceCount = createObjectInstances<ObstaclePtr>(tmpScene->getObstacles(), objectInstances);
182  // ManipulationObjects
183  objectInstanceCount += createObjectInstances<ManipulationObjectPtr>(tmpScene->getManipulationObjects(), objectInstances);
184 
185  importObjectsIntoPriorKnowledge(objectInstances);
186 
187  for (auto instancePair : objectInstances)
188  {
189  objectInstancesMemoryPrx->addEntity(instancePair.second);
190  }
191 
192  ARMARX_INFO << "Added " << objectInstanceCount << " instances to working memory";
193 
194  return true;
195  }
196 
197 
198  ScenePtr SimoxSceneImporter::createTempScene(const std::string& tmpPath, VirtualRobot::ScenePtr scene)
199  {
200  if (!scene)
201  {
202  return ScenePtr();
203  }
204 
205  // store scene string for saving scene file at the end
206  std::stringstream ss;
207  ss << "<Scene name='" << scene->getName() << "'>\n\n";
208 
209  fs::path sceneFileComplete = sceneFile;
210  std::string scenePath = sceneFileComplete.parent_path().c_str();
211  fs::path sceneFileNew = tmpPath / sceneFileComplete.filename();
212 
213  // Obstacles
214  std::vector<ObstaclePtr> obstacles = scene->getObstacles();
215  // ManipulationObjects
216  std::vector<ManipulationObjectPtr> manipulationObjects = scene->getManipulationObjects();
217  obstacles.insert(obstacles.end(), manipulationObjects.begin(), manipulationObjects.end());
218 
219  // loop over all scene objects
220  for (ObstaclePtr obstacle : obstacles)
221  {
222  std::vector<std::string> absoluteVisualizationFilenames;
223 
224  // get absolute paths to the required visualization files
225  getAbsoluteVisualizationFilenames(obstacle, absoluteVisualizationFilenames);
226 
227  // create old/new file mapping
228  std::map<std::string, std::string> newFilenames;
229  copyFilesToTempDir(absoluteVisualizationFilenames, tmpPath, scenePath, newFilenames);
230 
231  // update visu and col model filenames to new locations
232  setNewVisualizationFilenames(obstacle, newFilenames);
233 
234  // set the name of the original name if it none was present
235  std::string origFilename = obstacle->getFilename();
236 
237  if (origFilename.empty())
238  {
239  // create new filename
240  origFilename += obstacle->getName();
241  origFilename += ".xml";
242  }
243 
244  // copy the objects XML file to the temp directory
245  fs::path localFile = tmpPath / fs::path(origFilename).filename();
246  std::string localTmpFile = localFile.string();
247  ARMARX_INFO << "Saving modified ManipulationObject to " << localTmpFile << " (original file: " << scenePath << "/" << origFilename << ")";
248 
249  fs::path absPath = fs::absolute(tmpPath);
250  saveObstacleAsManipulationObject(obstacle, localTmpFile, absPath.string());
251 
252  // add XML to the stringstream
253  ss << "\t<ManipulationObject name='" << obstacle->getName() << "'>\n";
254  ss << "\t\t<File>" << localFile.filename().string() << "</File>\n";
255  ss << obstacle->getPhysics().toXML(2);
256  ss << "\t</ManipulationObject>\n\n";
257  }
258 
259  ss << "</Scene>\n";
260 
261  // save scene file (not needed within memory since only the manipulation objects are used in workingMemory), just for testing
262  ARMARX_LOG << "Saving scenefile from " << sceneFile << " to " << sceneFileNew.c_str();
263  std::string sceneString = ss.str();
264  BaseIO::writeXMLFile(sceneFileNew.c_str(), sceneString, true);
265 
266  return SceneIO::loadScene(sceneFileNew.string());
267  }
268 
269 
270  void SimoxSceneImporter::getAbsoluteVisualizationFilenames(ObstaclePtr obstacle, std::vector<std::string>& absoluteFilenames)
271  {
272  if (obstacle->getVisualization())
273  {
274  SoNode* visuNode = CoinVisualizationFactory::getCoinVisualization(obstacle->getVisualization());
275 
276  EntityWrappers::SimoxObjectWrapper::GetAllFilenames(visuNode, absoluteFilenames, obstacle->getVisualization()->getFilename());
277  std::string visuFile = obstacle->getVisualization()->getFilename();
278 
279  if (!visuFile.empty())
280  {
281  absoluteFilenames.push_back(visuFile);
282  }
283  }
284 
285  if (obstacle->getCollisionModel() && obstacle->getCollisionModel()->getVisualization())
286  {
287  SoNode* colNode = CoinVisualizationFactory::getCoinVisualization(obstacle->getCollisionModel()->getVisualization());
288  EntityWrappers::SimoxObjectWrapper::GetAllFilenames(colNode, absoluteFilenames, obstacle->getCollisionModel()->getVisualization()->getFilename());
289  std::string visuFile = obstacle->getCollisionModel()->getVisualization()->getFilename();
290 
291  if (!visuFile.empty())
292  {
293  absoluteFilenames.push_back(visuFile);
294  }
295  }
296  }
297 
298 
299  void SimoxSceneImporter::copyFilesToTempDir(const std::vector<std::string>& files, const std::string& tmpPath, const std::string& origPath, std::map<std::string, std::string>& newFilenameMapping)
300  {
301  fs::path tmpDir = tmpPath;
302 
303  for (size_t i = 0; i < files.size(); i++)
304  {
305  fs::path origFile = files[i];
306  std::string relativePath = fs::absolute(files[i]).string();
307  VirtualRobot::BaseIO::makeRelativePath(fs::absolute(origPath).string(), relativePath);
308  fs::path tmpFile = tmpDir / fs::path(relativePath);
309 
310  ARMARX_INFO << "\norigFile:" << origFile.c_str()
311  << "\n -> relPathS:" << relativePath
312  << "\n -> tmpFile:" << tmpFile.c_str();
313 
314  if (!fs::exists(origFile))
315  {
316  ARMARX_ERROR << "File does not exist:" << origFile.c_str();
317  continue;
318  }
319 
320  if (!fs::is_regular_file(origFile))
321  {
322  ARMARX_ERROR << "Not a regular file: " << origFile.c_str();
323  continue;
324  }
325 
326  if (fs::is_directory(origFile))
327  {
328  ARMARX_ERROR << "File is a directory:" << origFile.c_str();
329  continue;
330  }
331 
332  ARMARX_LOG << "Copying file from " << origFile.c_str() << " to " << tmpFile.c_str();
333  fs::create_directories(tmpFile.parent_path());
334  // int r = system(std::string("cp \"" + origFile.string() + "\" \"" + tmpFile.string() + "\"").c_str());
335  // if (r != 0)
336  // {
337  // ARMARX_INFO << "Coyping failed";
338  // }
339  fs::copy_file(origFile, tmpFile, fs::copy_options::overwrite_existing);
340  newFilenameMapping[origFile.string()] = fs::absolute(tmpFile).string();//relativePath;
341  }
342  }
343 
344 
345  void SimoxSceneImporter::setNewVisualizationFilenames(ObstaclePtr obstacle, std::map<std::string, std::string>& newFilenames)
346  {
347  if (obstacle->getVisualization())
348  {
349  std::string visuFile = obstacle->getVisualization()->getFilename();
350  std::string newVisuFile = newFilenames[visuFile];
351 
352  if (!newVisuFile.empty())
353  {
354  obstacle->getVisualization()->setFilename(newVisuFile, obstacle->getVisualization()->usedBoundingBoxVisu());
355  }
356  }
357 
358  if (obstacle->getCollisionModel() && obstacle->getCollisionModel()->getVisualization())
359  {
360  std::string visuFile = obstacle->getCollisionModel()->getVisualization()->getFilename();
361  std::string newVisuFile = newFilenames[visuFile];
362 
363  if (!newVisuFile.empty())
364  {
365  obstacle->getCollisionModel()->getVisualization()->setFilename(newVisuFile, obstacle->getCollisionModel()->getVisualization()->usedBoundingBoxVisu());
366  ARMARX_INFO << " COLLISION> " << obstacle->getCollisionModel()->getVisualization()->getFilename();
367  }
368  }
369  }
370 
371 
372  bool SimoxSceneImporter::saveObstacleAsManipulationObject(ObstaclePtr object, const std::string& xmlFile, const std::string& tmpPath)
373  {
374  THROW_VR_EXCEPTION_IF(!object, "NULL object");
375 
376  std::string xmlString = object->toXML(tmpPath);
377 
378  // This fix is needed until Simox uses virtual toXML() method
379  ManipulationObject* manip = dynamic_cast<ManipulationObject*>(object.get());
380 
381  if (manip)
382  {
383  xmlString = manip->toXML(tmpPath);
384  }
385 
386  // HACK: right now we ware only able to process manipulation objects -> convert it the hard way
387  xmlString = simox::alg::replace_all(xmlString, "<Obstacle", "<ManipulationObject");
388  xmlString = simox::alg::replace_all(xmlString, "</Obstacle", "</ManipulationObject");
389 
390  return BaseIO::writeXMLFile(xmlFile, xmlString, true);
391  }
392 
393 
394  template <typename T>
395  int SimoxSceneImporter::createObjectInstances(std::vector<T> obstacles, std::map<ObstaclePtr, ObjectInstanceBasePtr>& objectInstances)
396  {
397  int objectCount = 0;
398 
399  for (size_t i = 0; i < obstacles.size(); i++)
400  {
401  T obstacle = obstacles[i];
402  ObjectInstanceBasePtr obstacleInstance = createInstance(obstacle);
403 
404  if (obstacle && obstacleInstance)
405  {
406  objectInstances[obstacle] = obstacleInstance;
407  objectCount++;
408  }
409  }
410 
411  return objectCount;
412  }
413 
414 
415  ObjectInstanceBasePtr SimoxSceneImporter::createInstance(SceneObjectPtr sceneObject)
416  {
417  if (!sceneObject)
418  {
419  return ObjectInstancePtr();
420  }
421 
422  std::string objectName = sceneObject->getName();
423  ObjectInstancePtr objectInstance = new ObjectInstance(objectName);
424 
425  objectInstance->setExistenceCertainty(1.0f);
426 
427  // assume object class = object name for now
428  objectInstance->setClass(objectName, 1.0f);
429 
430  // position
431  Eigen::Vector3f position = sceneObject->getGlobalPose().block(0, 3, 3, 1);
432  armarx::FramedPositionBasePtr objectPosition = new armarx::FramedPosition(position, armarx::GlobalFrame, "");
433  objectInstance->setPosition(objectPosition);
434 
435  //orientation
436  armarx::FramedOrientationBasePtr objectOrientation = new armarx::FramedOrientation(sceneObject->getGlobalPose(), armarx::GlobalFrame, "");
437  objectInstance->setOrientation(objectOrientation);
438 
439  return objectInstance;
440  }
441 
442 
443  void SimoxSceneImporter::importObjectsIntoPriorKnowledge(std::map<VirtualRobot::ObstaclePtr, ObjectInstanceBasePtr>& objectInstances)
444  {
445  GridFileManagerPtr fileManager(new GridFileManager(dataBasePrx));
446 
447  std::map<VirtualRobot::ObstaclePtr, ObjectInstanceBasePtr>::iterator it;
448 
449  for (it = objectInstances.begin(); it != objectInstances.end(); it++)
450  {
451  Obstacle* obstacle = it->first.get();
452 
453  ManipulationObject* manip = dynamic_cast<ManipulationObject*>(obstacle);
454 
455  if (manip)
456  {
457  obstacle = manip;
458  }
459 
460  std::string simoxFilename = obstacle->getFilename();
461 
462  fs::path visuFName = obstacle->getVisualization()->getFilename();
463  fs::path collisionFName = obstacle->getCollisionModel()->getVisualization()->getFilename();
464 
465  if (collisionFName.empty())
466  {
467  collisionFName = visuFName;
468  }
469 
470  {
471  ObjectClassPtr newClass = new ObjectClass();
472  newClass->setName(obstacle->getName());
473 
474  EntityWrappers::SimoxObjectWrapperPtr simoxWrapper = newClass->addWrapper(new EntityWrappers::SimoxObjectWrapper(fileManager));
475  ARMARX_INFO << "Store file: " << visuFName.string();
476  ARMARX_INFO << "simoxFilename: " << simoxFilename;
477  ARMARX_INFO << "visuFName.string(): " << visuFName.string();
478  ARMARX_INFO << "collisionFName.string(): " << collisionFName.string();
479  simoxWrapper->setAndStoreManipulationFile(simoxFilename, filesDBName);
480 
481  EntityBasePtr ent = classesSegmentPrx->getEntityByName(newClass->getName());
482 
483  if (ent)
484  {
485  ARMARX_IMPORTANT << "Updating existing entity " << ent->getName() << "(Id: " << ent->getId() << ")";
486  classesSegmentPrx->updateEntity(ent->getId(), ent);
487  }
488  else
489  {
490  classesSegmentPrx->addEntity(newClass);
491  }
492  }
493  }
494  }
495 }
files
Use of this software is granted under one of the following two to be chosen freely by the user Boost Software License Version Marcin Kalicinski Permission is hereby free of to any person or organization obtaining a copy of the software and accompanying documentation covered by this and transmit the and to prepare derivative works of the and to permit third parties to whom the Software is furnished to do all subject to the including the above license this restriction and the following must be included in all copies of the in whole or in and all derivative works of the unless such copies or derivative works are solely in the form of machine executable object code generated by a source language processor THE SOFTWARE IS PROVIDED AS WITHOUT WARRANTY OF ANY EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF FITNESS FOR A PARTICULAR TITLE AND NON INFRINGEMENT IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN TORT OR ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE The MIT Marcin Kalicinski Permission is hereby free of to any person obtaining a copy of this software and associated documentation files(the "Software")
armarx::ManagedIceObject::getIceManager
IceManagerPtr getIceManager() const
Returns the IceManager.
Definition: ManagedIceObject.cpp:353
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
JSONObject.h
VirtualRobot
Definition: FramedPose.h:43
Pose.h
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:62
GridFileManager.h
memoryx
VirtualRobot headers.
Definition: CommonPlacesTester.cpp:48
ObjectClass.h
scene3D::ScenePtr
std::shared_ptr< Scene > ScenePtr
Definition: PointerDefinitions.h:36
armarx::starts_with
bool starts_with(const std::string &haystack, const std::string &needle)
Definition: StringHelpers.cpp:43
memoryx::SimoxSceneImporter::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: SimoxSceneImporter.cpp:68
memoryx::ObjectInstancePtr
IceInternal::Handle< ObjectInstance > ObjectInstancePtr
Definition: ObjectInstance.h:42
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
memoryx::EntityWrappers::SimoxObjectWrapperPtr
IceInternal::Handle< SimoxObjectWrapper > SimoxObjectWrapperPtr
Definition: SimoxObjectWrapper.h:268
memoryx::SimoxSceneImporter::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: SimoxSceneImporter.cpp:59
ARMARX_LOG
#define ARMARX_LOG
Definition: Logging.h:163
memoryx::MongoSerializer
Definition: MongoSerializer.h:40
SimoxObjectWrapper.h
ObjectInstance.h
armarx::VariantType::FramedOrientation
const VariantTypeId FramedOrientation
Definition: FramedPose.h:40
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
memoryx::GridFileManagerPtr
std::shared_ptr< GridFileManager > GridFileManagerPtr
Definition: AbstractEntityWrapper.h:32
SimoxSceneImporter.h
scene3D::SceneObjectPtr
boost::intrusive_ptr< SceneObject > SceneObjectPtr
Definition: PointerDefinitions.h:40
memoryx::ObjectClassPtr
IceInternal::Handle< ObjectClass > ObjectClassPtr
Definition: ObjectClass.h:35
T
float T
Definition: UnscentedKalmanFilterTest.cpp:35
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:39
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::ManagedIceObject::getCommunicator
Ice::CommunicatorPtr getCommunicator() const
Definition: ManagedIceObject.cpp:431
memoryx::EntityWrappers::SimoxObjectWrapper::GetAllFilenames
static void GetAllFilenames(SoNode *node, std::vector< std::string > &storeFilenames, const std::string &origFile="")
GetAllFilenames walks node and appends absolute paths of all found SoFile, SoImage,...
Definition: SimoxObjectWrapper.cpp:917
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