ObjectFinder.cpp
Go to the documentation of this file.
1 #include <VirtualRobot/XML/ObjectIO.h>
2 
3 #include <set>
4 
5 #include <SimoxUtility/algorithm/string.h>
6 #include <SimoxUtility/filesystem/list_directory.h>
7 
11 
12 #include "ObjectFinder.h"
13 
14 
15 namespace armarx
16 {
17  namespace fs = std::filesystem;
18 
19 
20  ObjectFinder::ObjectFinder(const std::string& objectsPackageName, const ObjectFinder::path& relObjectsDir) :
21  packageName(objectsPackageName), relObjectsDir(relObjectsDir)
22  {
23  Logging::setTag("ObjectFinder");
24  }
25 
26  void ObjectFinder::setPath(const std::string& path)
27  {
28  packageName = path;
29  absPackageDataDir.clear();
30  }
31 
32  std::string ObjectFinder::getPackageName() const
33  {
34  return packageName;
35  }
36 
37  void ObjectFinder::init() const
38  {
39  if (absPackageDataDir.empty())
40  {
41  CMakePackageFinder packageFinder(packageName);
42  absPackageDataDir = packageFinder.getDataDir();
43  if (absPackageDataDir.empty())
44  {
45  ARMARX_WARNING << "Could not find package '" << packageName << "'.";
46  // throw LocalException() << "Could not find package '" << packageName << "'.";
47  }
48  else
49  {
50  ARMARX_VERBOSE << "Objects root directory: " << _rootDirAbs();
51 
52  // make sure this data path is available => e.g. for findArticulatedObjects
53  armarx::ArmarXDataPath::addDataPaths(std::vector<std::string> {absPackageDataDir});
54  }
55  }
56  }
57 
58 
59  bool ObjectFinder::isDatasetDirValid(const path& path) const
60  {
61  return std::filesystem::is_directory(path);
62  }
63 
64 
65  std::optional<ObjectInfo> ObjectFinder::findObject(const std::string& dataset, const std::string& name) const
66  {
67  init();
68  if (!_ready())
69  {
70  return std::nullopt;
71  }
72  if (!dataset.empty())
73  {
74  return ObjectInfo(packageName, absPackageDataDir, relObjectsDir, dataset, name);
75  }
76  // Search for object in datasets.
77  const std::vector<std::string>& datasets = getDatasets();
78  for (const std::string& ds : datasets)
79  {
80  if (fs::is_directory(_rootDirAbs() / ds / name))
81  {
82  return ObjectInfo(packageName, absPackageDataDir, relObjectsDir, ds, name);
83  }
84  }
85 
86  std::stringstream ss;
87  ss << "Did not find object '" << name << "' in any of these datasets:\n";
88  for (const auto& ds : datasets)
89  {
90  ss << "- " << ds << "\n";
91  }
92  ss << "Objects root directory: " << _rootDirAbs();
93  ARMARX_VERBOSE << ss.str();
94 
95  return std::nullopt;
96  }
97 
98  std::optional<ObjectInfo> ObjectFinder::findObject(const std::string& nameOrID) const
99  {
100  return findObject(ObjectID(nameOrID));
101  }
102 
103  std::optional<ObjectInfo> ObjectFinder::findObject(const ObjectID& id) const
104  {
105  return findObject(id.dataset(), id.className());
106  }
107 
108  std::optional<ObjectInfo> ObjectFinder::findObject(const objpose::ObjectPose& obj) const
109  {
110  return findObject(obj.objectID);
111  }
112 
113  std::vector<std::string> ObjectFinder::getDatasets() const
114  {
115  // init(); // Done by called methods.
116  std::vector<std::string> datasets;
117  for (const path& dir : getDatasetDirectories())
118  {
119  datasets.push_back(dir.filename());
120  }
121  return datasets;
122  }
123 
124  std::vector<ObjectFinder::path> ObjectFinder::getDatasetDirectories() const
125  {
126  init();
127  if (!_ready())
128  {
129  return {};
130  }
131  const bool local = false;
132  std::vector<path> dirs = simox::fs::list_directory(_rootDirAbs(), local);
133  std::vector<path> datasetDirs;
134  for (const path& p : dirs)
135  {
136  if (isDatasetDirValid(p))
137  {
138  datasetDirs.push_back(p);
139  }
140  }
141  return datasetDirs;
142  }
143 
144  std::vector<ObjectInfo> ObjectFinder::findAllObjects(bool checkPaths) const
145  {
146  init();
147  if (!_ready())
148  {
149  return {};
150  }
151  const bool local = true;
152  std::vector<ObjectInfo> objects;
153  for (const path& datasetDir : simox::fs::list_directory(_rootDirAbs(), local))
154  {
155  if (isDatasetDirValid(_rootDirAbs() / datasetDir))
156  {
157  std::vector<ObjectInfo> dataset = findAllObjectsOfDataset(datasetDir, checkPaths);
158  for (const auto& o : dataset)
159  {
160  objects.push_back(o);
161  }
162  }
163  }
164  return objects;
165  }
166 
167  std::vector<armem::articulated_object::ArticulatedObjectDescription> ObjectFinder::findAllArticulatedObjects(bool checkPaths) const
168  {
169  init();
170  if (!_ready())
171  {
172  return {};
173  }
174 
175  const bool local = true;
176 
177  std::vector<armem::articulated_object::ArticulatedObjectDescription> objects;
178  for (const path& datasetDir : simox::fs::list_directory(_rootDirAbs(), local))
179  {
180  if (isDatasetDirValid(_rootDirAbs() / datasetDir))
181  {
182  const auto dataset = findAllArticulatedObjectsOfDataset(datasetDir, checkPaths);
183  objects.insert(objects.end(), dataset.begin(), dataset.end());
184  }
185  }
186  return objects;
187  }
188 
189  std::map<std::string, std::vector<ObjectInfo>>
191  {
192  // init(); // Done by called methods.
193  std::map<std::string, std::vector<ObjectInfo>> objects;
194  for (const std::string& dataset : getDatasets())
195  {
196  objects[dataset] = findAllObjectsOfDataset(dataset, checkPaths);
197  }
198  return objects;
199  }
200 
201  std::vector<ObjectInfo> ObjectFinder::findAllObjectsOfDataset(const std::string& dataset, bool checkPaths) const
202  {
203  init();
204  if (!_ready())
205  {
206  return {};
207  }
208  path datasetDir = _rootDirAbs() / dataset;
209  if (!fs::is_directory(datasetDir))
210  {
211  ARMARX_WARNING << "Expected dataset directory for dataset '" << dataset << "': \n"
212  << datasetDir;
213  return {};
214  }
215 
216  std::vector<ObjectInfo> objects;
217  const bool local = true;
218  for (const path& dir : simox::fs::list_directory(datasetDir, local))
219  {
220  if (fs::is_directory(datasetDir / dir))
221  {
222  ObjectInfo object(packageName, absPackageDataDir, relObjectsDir, dataset, dir.filename());
223  object.setLogError(logObjectDiscoveryError);
224 
225  if (!checkPaths || object.checkPaths())
226  {
227  objects.push_back(object);
228  }
229  }
230  }
231  return objects;
232  }
233 
234 
235  std::unordered_map<std::string, std::vector<armem::articulated_object::ArticulatedObjectDescription>>
237  {
238  init();
239  if (!_ready())
240  {
241  return {};
242  }
243 
244  const bool local = true;
245 
246  std::unordered_map<std::string, std::vector<armem::articulated_object::ArticulatedObjectDescription>> datasets;
247  for (const path& datasetDir : simox::fs::list_directory(_rootDirAbs(), local))
248  {
249  if (isDatasetDirValid(_rootDirAbs() / datasetDir))
250  {
251  const auto dataset = findAllArticulatedObjectsOfDataset(datasetDir, checkPaths);
252  datasets[datasetDir] = dataset;
253  }
254  }
255  return datasets;
256  }
257 
258 
259  std::vector<armem::articulated_object::ArticulatedObjectDescription>
260  ObjectFinder::findAllArticulatedObjectsOfDataset(const std::string& dataset, bool checkPaths) const
261  {
262  init();
263  if (!_ready())
264  {
265  return {};
266  }
267  path datasetDir = _rootDirAbs() / dataset;
268  if (!isDatasetDirValid(datasetDir))
269  {
270  ARMARX_WARNING << "Expected dataset directory for dataset '" << dataset << "': \n"
271  << datasetDir;
272  return {};
273  }
274 
275  std::vector<armem::articulated_object::ArticulatedObjectDescription> objects;
276  const bool local = true;
277  for (const path& dir : simox::fs::list_directory(datasetDir, local))
278  {
279  if (fs::is_directory(datasetDir / dir))
280  {
281  ObjectInfo object(packageName, absPackageDataDir, relObjectsDir, dataset, dir.filename());
282  std::optional<PackageFileLocation> modelFile = object.getArticulatedModel();
283  if (modelFile.has_value())
284  {
286  {
287  .name = object.idStr(),
288  .xml = {modelFile->package, modelFile->relativePath},
289  .visualization = {},
290  .info = {}
291  // .dataset = dataset
292  });
293  }
294  }
295  }
296  return objects;
297  }
298 
299  VirtualRobot::ManipulationObjectPtr
300  ObjectFinder::loadManipulationObject(const std::optional<ObjectInfo>& ts)
301  {
302  if (!ts)
303  {
304  return nullptr;
305  }
306  const auto data = ts->simoxXML();
308  std::string abs;
309  if (!ArmarXDataPath::SearchReadableFile(data.relativePath, abs))
310  {
311  return nullptr;
312  }
313  return VirtualRobot::ObjectIO::loadManipulationObject(abs);
314  }
315  VirtualRobot::ManipulationObjectPtr
317  {
318  return loadManipulationObject(findObject(obj));
319  }
320  VirtualRobot::ObstaclePtr
321  ObjectFinder::loadObstacle(const std::optional<ObjectInfo>& ts)
322  {
323  if (!ts)
324  {
325  return nullptr;
326  }
327  const auto data = ts->simoxXML();
329  std::string abs;
330  if (!ArmarXDataPath::SearchReadableFile(data.relativePath, abs))
331  {
332  return nullptr;
333  }
334  return VirtualRobot::ObjectIO::loadObstacle(abs);
335  }
336  VirtualRobot::ObstaclePtr
338  {
339  return loadObstacle(findObject(obj));
340  }
341 
342 
343  static std::vector<std::string> _loadNames(
344  const ObjectFinder& finder,
345  const ObjectID& objectID,
346  const bool includeClassName,
347  const std::function<std::optional<std::vector<std::string>>(const ObjectInfo&)> loadNamesFn)
348  {
349  std::vector<std::string> names;
350  if (includeClassName)
351  {
352  names.push_back(simox::alg::to_lower(objectID.className()));
353  }
354  if (std::optional<ObjectInfo> info = finder.findObject(objectID))
355  {
356  if (std::optional<std::vector<std::string>> loadedNames = loadNamesFn(*info))
357  {
358  // Source: https://stackoverflow.com/a/201729
359  names.insert(names.end(), loadedNames->begin(), loadedNames->end());
360  }
361  }
362  return names;
363  }
364  std::vector<std::string> ObjectFinder::loadRecognizedNames(const ObjectID& objectID, bool includeClassName) const
365  {
366  return _loadNames(*this, objectID, includeClassName, [](const ObjectInfo & info)
367  {
368  return info.loadRecognizedNames();
369  });
370  }
371  std::vector<std::string> ObjectFinder::loadSpokenNames(const ObjectID& objectID, bool includeClassName) const
372  {
373  return _loadNames(*this, objectID, includeClassName, [](const ObjectInfo & info)
374  {
375  return info.loadSpokenNames();
376  });
377  }
378 
380  {
381  logObjectDiscoveryError = logEnabled;
382  }
383 
384  ObjectFinder::path ObjectFinder::_rootDirAbs() const
385  {
386  return absPackageDataDir / packageName / relObjectsDir;
387  }
388 
389  ObjectFinder::path ObjectFinder::_rootDirRel() const
390  {
391  return packageName;
392  }
393 
394  bool ObjectFinder::_ready() const
395  {
396  return !absPackageDataDir.empty();
397  }
398 
399 }
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::ObjectFinder::findAllArticulatedObjectsOfDataset
std::vector< armem::articulated_object::ArticulatedObjectDescription > findAllArticulatedObjectsOfDataset(const std::string &dataset, bool checkPaths) const
Definition: ObjectFinder.cpp:260
armarx::ObjectID
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
Definition: ObjectID.h:11
armarx::ObjectFinder::loadObstacle
static VirtualRobot::ObstaclePtr loadObstacle(const std::optional< ObjectInfo > &ts)
Definition: ObjectFinder.cpp:321
armarx::armem::robot_state::description::RobotDescription
Definition: types.h:44
armarx::ObjectFinder::findAllObjects
std::vector< ObjectInfo > findAllObjects(bool checkPaths=true) const
Definition: ObjectFinder.cpp:144
armarx::armem::attachment::ObjectID
armem::MemoryID ObjectID
Definition: types.h:79
armarx::ArmarXDataPath::FindPackageAndAddDataPath
static bool FindPackageAndAddDataPath(const std::string &packageName)
Search for the package and add its data path if it was found.
Definition: ArmarXDataPath.cpp:829
armarx::ObjectFinder::ObjectFinder
ObjectFinder(const std::string &objectsPackageName=DefaultObjectsPackageName, const path &relObjectsDir=DefaultObjectsDirectory)
Definition: ObjectFinder.cpp:20
armarx::ObjectFinder::path
std::filesystem::path path
Definition: ObjectFinder.h:27
armarx::CMakePackageFinder
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
Definition: CMakePackageFinder.h:53
armarx::ObjectFinder::loadManipulationObject
static VirtualRobot::ManipulationObjectPtr loadManipulationObject(const std::optional< ObjectInfo > &ts)
Definition: ObjectFinder.cpp:300
armarx::ObjectFinder::setLogObjectDiscoveryError
void setLogObjectDiscoveryError(bool logEnabled)
Definition: ObjectFinder.cpp:379
armarx::ObjectInfo::loadRecognizedNames
std::optional< std::vector< std::string > > loadRecognizedNames() const
Load names to use when matched when recognizing an object by name.
Definition: ObjectInfo.cpp:326
armarx::ObjectFinder
Used to find objects in the ArmarX objects repository [1] (formerly [2]).
Definition: ObjectFinder.h:23
armarx::ObjectFinder::setPath
void setPath(const std::string &path)
Definition: ObjectFinder.cpp:26
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:253
armarx::ObjectID::className
std::string className() const
Definition: ObjectID.h:28
armarx::ObjectFinder::findAllObjectsOfDataset
std::vector< ObjectInfo > findAllObjectsOfDataset(const std::string &dataset, bool checkPaths=true) const
Definition: ObjectFinder.cpp:201
armarx::ObjectFinder::findAllArticulatedObjectsByDataset
std::unordered_map< std::string, std::vector< armem::articulated_object::ArticulatedObjectDescription > > findAllArticulatedObjectsByDataset(bool checkPaths=true) const
Definition: ObjectFinder.cpp:236
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
armarx::ObjectFinder::loadSpokenNames
std::vector< std::string > loadSpokenNames(const ObjectID &objectID, bool includeClassName=false) const
Load names to use when verbalizing an object name.
Definition: ObjectFinder.cpp:371
armarx::ObjectFinder::loadRecognizedNames
std::vector< std::string > loadRecognizedNames(const ObjectID &objectID, bool includeClassName=false) const
Load names to use when matched when recognizing an object by name.
Definition: ObjectFinder.cpp:364
armarx::ObjectFinder::findAllObjectsByDataset
std::map< std::string, std::vector< ObjectInfo > > findAllObjectsByDataset(bool checkPaths=true) const
Definition: ObjectFinder.cpp:190
ExpressionException.h
armarx::ArmarXDataPath::SearchReadableFile
static bool SearchReadableFile(const std::string &querryFileName, std::string &resultFileName, bool verbose=true)
Definition: ArmarXDataPath.cpp:218
CMakePackageFinder.h
armarx::ObjectFinder::getDatasetDirectories
std::vector< path > getDatasetDirectories() const
Definition: ObjectFinder.cpp:124
armarx::objpose::ObjectPose::objectID
armarx::ObjectID objectID
The object ID, i.e. dataset, class name and instance name.
Definition: ObjectPose.h:58
armarx::armem::robot_state::description::RobotDescription::name
std::string name
Definition: types.h:48
armarx::viz::data::ElementFlags::names
const simox::meta::IntEnumNames names
Definition: json_elements.cpp:14
armarx::ArmarXDataPath::addDataPaths
static void addDataPaths(const std::string &dataPathList)
Definition: ArmarXDataPath.cpp:559
armarx::ObjectInfo::loadSpokenNames
std::optional< std::vector< std::string > > loadSpokenNames() const
Load names to use when verbalizing an object name.
Definition: ObjectInfo.cpp:332
armarx::ObjectFinder::findObject
std::optional< ObjectInfo > findObject(const std::string &dataset, const std::string &name) const
Definition: ObjectFinder.cpp:65
armarx::ObjectFinder::findAllArticulatedObjects
std::vector< armem::articulated_object::ArticulatedObjectDescription > findAllArticulatedObjects(bool checkPaths) const
Definition: ObjectFinder.cpp:167
armarx::ObjectFinder::getDatasets
std::vector< std::string > getDatasets() const
Definition: ObjectFinder.cpp:113
armarx::Logging::setTag
void setTag(const LogTag &tag)
Definition: Logging.cpp:55
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::ObjectFinder::getPackageName
std::string getPackageName() const
Definition: ObjectFinder.cpp:32
ArmarXDataPath.h
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::objpose::ObjectPose
An object pose as stored by the ObjectPoseStorage.
Definition: ObjectPose.h:36
armarx::ObjectInfo
Accessor for the object files.
Definition: ObjectInfo.h:37
ObjectFinder.h