ArmarXDataPath.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5*
6* ArmarX is free software; you can redistribute it and/or modify
7* it under the terms of the GNU General Public License version 2 as
8* published by the Free Software Foundation.
9*
10* ArmarX is distributed in the hope that it will be useful, but
11* WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17*
18* @package ArmarXCore::core
19* @author Nikolaus Vahrenkamp
20* @date 2012
21* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22* GNU General Public License
23*/
24
25#include "ArmarXDataPath.h" // for ArmarXDataPath
26
27#include <algorithm> // for min, fill, find
28#include <cstdlib> // for getenv
29#include <filesystem>
30#include <fstream>
31#include <regex>
32#include <sstream> // for operator<<, char_traits, etc
33#include <string> // for basic_string, string, etc
34#include <vector> // for vector
35
36#include <boost/regex.hpp>
37
38#include <IceUtil/Handle.h> // for HandleBase
39
40#include <SimoxUtility/algorithm/string/string_tools.h>
41#include <SimoxUtility/simox/SimoxPath.h>
42
44#include "ArmarXCore/core/exceptions/Exception.h" // for LocalException
45#include "ArmarXCore/core/logging/LogSender.h" // for LogSender
47#include <ArmarXCore/core/logging/Logging.h> // for ARMARX_WARNING_S, etc
49#include <ArmarXCore/core/util/StringHelpers.h> // for Contains, VAROUT
51
53
54//#include <execinfo.h>
55//#include <stdio.h>
56
57namespace armarx
58{
59 namespace fs = std::filesystem;
60
61 // static void printBacktrace()
62 // {
63 // void* callstack[128];
64 // int i, frames = backtrace(callstack, 128);
65 // char** strs = backtrace_symbols(callstack, frames);
66 // for (i = 0; i < frames; ++i)
67 // {
68 // printf("%s\n", strs[i]);
69 // }
70 // free(strs);
71 // }
72
74 {
76 {
77 // printf("Creating ArmarXDataPath_Data, this: %p\n", (void*)this);
78 // printBacktrace();
79 }
80
82 {
83 // This is super weird!
84 // This global object should exist only once.
85 // However, we get two instances if run ArmarXGUIRun
86 // This actually causes a double free if we put these variables
87 // as static variables in the class (the vector is freed twice).
88
89 // We now put these variables in this .cpp file to prevent double free.
90 // However, this means we have multiple instances now!
91 // How can this even happen?
92 // Are there two instances of ArmarXCore.so loaded in the GUI?
93
94 // printf("Destroying ArmarXDataPath_Data(), this: %p\n", (void*)this);
95 // printBacktrace();
96 }
97
98 std::vector<std::string> dataPaths;
99 bool initialized = false;
100 };
101
102 static ArmarXDataPath_Data ArmarXDataPath_data;
103
104 ArmarXDataPath::ArmarXDataPath()
105 {
106 }
107
108 bool
109 ArmarXDataPath::getAbsolutePath(const std::string& relativeFilename,
110 std::string& storeAbsoluteFilename,
111 const std::vector<std::string>& additionalSearchPaths,
112 bool verbose)
113 {
114
115 init();
116
117 const std::filesystem::path filename(relativeFilename);
118
119 // first: check current path
120 if (std::filesystem::exists(filename))
121 {
122 storeAbsoluteFilename = filename.string();
123 return true;
124 }
125
126 const auto search = [&filename, &storeAbsoluteFilename](const auto& bases)
127 {
128 for (const auto& currentPath : bases)
129 {
130 std::filesystem::path path(currentPath);
131
132 std::filesystem::path filenameComplete = path / filename;
133
134 if (std::filesystem::exists(filenameComplete))
135 {
136 storeAbsoluteFilename = filenameComplete.string();
137 return true;
138 }
139 }
140 return false;
141 };
142 const auto searchProject = [&search](const auto& project)
143 {
144 CMakePackageFinder finder(project);
145 auto pathsString = finder.getDataDir();
146 Ice::StringSeq projectDataPaths = simox::alg::split(pathsString, ";,");
147 return search(projectDataPaths);
148 };
149 {
150 if (search(additionalSearchPaths) || search(ArmarXDataPath_data.dataPaths))
151 {
152 return true;
153 }
154 }
155
156 //search for a package with the first part of the path (e.g.: ArmarxCore for the path ArmarXCore/foo/bar)
157 {
158 std::filesystem::path p = relativeFilename;
159
160 if (p.is_absolute())
161 {
162 p = std::filesystem::relative(p, "/");
163 }
164 while (p.has_parent_path())
165 {
166 if (p.parent_path() == ".")
167 {
168 p = p.filename();
169 }
170 else
171 {
172 p = p.parent_path();
173 }
174 }
175 const auto pstr = p.string();
176 if (!pstr.empty() && searchProject(pstr))
177 {
178 return true;
179 }
180 }
181
182 //search in all projects from getDefaultPackageNames()
184 {
185 for (const auto& project : Application::getInstance()->getArmarXPackageNames())
186 {
187 if (searchProject(project))
188 {
189 return true;
190 }
191 }
192 }
193
194 if (verbose)
195 {
196 ARMARX_WARNING_S << "Could not find file '" << relativeFilename << "'"
197 << "\n in the following additional paths: " << additionalSearchPaths
198 << "\n or in the following data paths: "
199 << ArmarXDataPath_data.dataPaths;
200 }
201
202 return false;
203 }
204
205 std::string
206 ArmarXDataPath::getAbsolutePath(const std::string& relativeFilename,
207 const std::vector<std::string>& additionalSearchPaths,
208 bool verbose)
209 {
210 std::string storeAbsoluteFilename;
211 getAbsolutePath(relativeFilename, storeAbsoluteFilename, additionalSearchPaths, verbose);
212 return storeAbsoluteFilename;
213 }
214
215 bool
216 ArmarXDataPath::SearchReadableFile(const std::string& queryFileName,
217 std::string& resultFileName,
218 bool verbose)
219 {
220 const auto file_ok = [](const std::string& f)
221 { return std::filesystem::exists(f) && std::ifstream(f).good(); };
222
223 //cases
224 // -absolute
225 // - readable -> done
226 // - not readable -> try to find part
227 // - relative
228 // - found path
229 // - readable -> done
230 // - not readable -> failure
231 // - failed to find path
232 // - search for sub parts -> try search again
233
234 if (std::filesystem::path{queryFileName}.is_absolute() && file_ok(queryFileName))
235 {
236 resultFileName = queryFileName;
237 return true;
238 }
239 //here queryFileName is always relative or the absolute is not ok
240 std::string found_file;
241 if (getAbsolutePath(queryFileName, found_file, {}, verbose) && file_ok(found_file))
242 {
243 resultFileName = found_file;
244 return true;
245 }
246 //now we need to try to search for package names
247 // try all strings ... of pattern /data/.../
248 std::size_t offset = 0;
249 while (offset != std::string::npos && offset < queryFileName.size())
250 {
251 // deal with paths like /prefix/data/foo/data/bar/file
252 // -> search for 'foo/data/bar/file' and 'bar/file'
253 static const std::string dataMarker = "/data/";
254 offset = queryFileName.find(dataMarker, offset);
255 if (offset == std::string::npos)
256 {
257 return false;
258 }
259 const std::string prefix_path = queryFileName.substr(0, offset);
260 offset += dataMarker.size();
261 const std::string path_in_data = queryFileName.substr(offset);
262
263 // Check for '.../VirtualRobot/data/...'
264 if (simox::alg::ends_with(prefix_path, "VirtualRobot"))
265 {
266 found_file = simox::SimoxPath::getVirtualRobotDataDir() / path_in_data;
267 if (file_ok(found_file))
268 {
269 resultFileName = found_file;
270 return true;
271 }
272 }
273
274 if (getAbsolutePath(path_in_data, found_file, {}, verbose) && file_ok(found_file))
275 {
276 resultFileName = found_file;
277 return true;
278 }
279 const std::size_t slash_offset = path_in_data.find("/");
280 if (slash_offset == std::string::npos)
281 {
282 return false;
283 }
284 const std::string package_name = path_in_data.substr(0, slash_offset);
285
286 if (FindPackageAndAddDataPath(package_name) && // found package
287 getAbsolutePath(path_in_data, found_file) && // found file
288 file_ok(found_file) // file ok
289 )
290 {
291 resultFileName = found_file;
292 return true;
293 }
294 }
295 return false;
296 }
297
298 std::string
299 ArmarXDataPath::getProject(const std::vector<std::string>& projects,
300 const std::string& relativeFilename)
301 {
302 std::filesystem::path fn(relativeFilename);
303 for (auto currentProject : projects)
304 {
305 armarx::CMakePackageFinder finder(currentProject);
306
307 if (!finder.packageFound())
308 {
309 ARMARX_VERBOSE_S << "ArmarX Package " << currentProject << " has not been found!";
310 continue;
311 }
312
313 //ARMARX_INFO_S << "Checking datapath: " << finder.getDataDir();
314 std::filesystem::path p(finder.getDataDir());
315 std::filesystem::path fnComplete = p / fn;
316
317 if (std::filesystem::exists(fnComplete))
318 {
319 //ARMARX_INFO_S << "Found in project " << currentProject;
320 return currentProject;
321 }
322 }
323
324 return std::string();
325 }
326
327 std::string
328 ArmarXDataPath::cleanPath(const std::string& filepathStr)
329 {
330 std::filesystem::path p(filepathStr);
331 std::filesystem::path result;
332
333 for (std::filesystem::path::iterator it = p.begin(); it != p.end(); ++it)
334 {
335 if (*it == ".." && it != p.begin())
336 {
337 // /a/b/.. is not necessarily /a if b is a symbolic link
338 bool isSymLink = false;
339
340 try
341 {
342 isSymLink = std::filesystem::is_symlink(result);
343 }
344 catch (std::filesystem::filesystem_error&)
345 {
346 }
347
348 if (isSymLink)
349 {
350 result /= *it;
351 }
352 // /a/b/../.. is not /a/b/.. under most circumstances
353 // We can end up with ..s in our result because of symbolic links
354 else if (result.filename() == "..")
355 {
356 result /= *it;
357 }
358 // Otherwise it should be safe to resolve the parent
359 else
360 {
361 result = result.parent_path();
362 }
363 }
364 else if (*it == ".")
365 {
366 // Ignore
367 }
368 else
369 {
370 // Just concatenate other path entries
371 result /= *it;
372 }
373 }
374
375 return result.string();
376 }
377
378 std::string
379 ArmarXDataPath::getRelativeArmarXPath(const std::string& absolutePathString)
380 {
381 init();
382
383 // traverse directories until root is reached
384 for (auto absolutePathPart = std::filesystem::path(absolutePathString);
385 absolutePathPart != absolutePathPart.parent_path();
386 absolutePathPart = absolutePathPart.parent_path())
387 {
388 for (const auto& dataPath : ArmarXDataPath_data.dataPaths)
389 {
390 const std::filesystem::path p(dataPath);
391
392 if (std::filesystem::equivalent(p, absolutePathPart))
393 {
394 return relativeTo(p.string(), absolutePathString);
395 }
396 }
397 }
398
399 throw LocalException() << "Could not make path relative to any ArmarX data path for '"
400 << absolutePathString << "'. "
401 << "Considered the following paths: "
402 << ArmarXDataPath_data.dataPaths;
403 return absolutePathString;
404 }
405
406 std::string
407 ArmarXDataPath::relativeTo(const std::string& fromStr, const std::string& toStr)
408 {
409 // Start at the root path. While they are the same, do nothing.
410 // When they first diverge, take the remainder of the two paths
411 // and replace the entire from path with ".." segments.
412 fs::path from(fromStr);
413 fs::path to(toStr);
414 fs::path::const_iterator fromIter = (from).begin();
415 fs::path::const_iterator toIter = (to).begin();
416 if (from.empty())
417 {
418 throw LocalException("From path is empty");
419 }
420 if (to.empty())
421 {
422 throw LocalException("To path is empty");
423 }
424 if (*fromIter != *toIter)
425 {
426 throw LocalException("From and to path do not have the same toplevel dir: ")
427 << VAROUT(fromStr) << VAROUT(toStr);
428 }
429 // Loop through both
430 while (fromIter != from.end() && toIter != to.end() && (*toIter) == (*fromIter))
431 {
432 ++toIter;
433 ++fromIter;
434 }
435
436 fs::path finalPath;
437 while (fromIter != from.end())
438 {
439 finalPath /= "..";
440 ++fromIter;
441 }
442
443 while (toIter != to.end())
444 {
445 finalPath /= *toIter;
446 ++toIter;
447 }
448
449 return finalPath.string();
450 }
451
452 bool
453 ArmarXDataPath::mergePaths(std::string pathStr, std::string subPathStr, std::string& result)
454 {
455 fs::path subPath(subPathStr);
456 pathStr = cleanPath(pathStr);
457 subPathStr = cleanPath(subPathStr);
458 fs::path strippedPath;
459 while (!subPath.empty())
460 {
461 if (Contains(pathStr, subPath.string()))
462 {
463 result = remove_trailing_separator(fs::path(pathStr) / strippedPath).string();
464 return true;
465 }
466 strippedPath = subPath.filename() / strippedPath;
467 subPath = subPath.parent_path();
468 }
469 result.clear();
470 return false;
471 }
472
473 void
474 ArmarXDataPath::initDataPaths(const std::string& dataPathList)
475 {
476 addDataPaths(dataPathList);
477 }
478
479 bool
481 {
482 const boost::regex e("\\$([a-zA-Z0-9_]+)");
483 const boost::regex e2("\\$\\{([a-zA-Z0-9_]+)\\}");
484 boost::match_results<std::string::const_iterator> what;
485 bool found = false;
486 auto replaceVars = [&](const boost::regex& e)
487 {
488 bool found_match = boost::regex_search(string, what, e);
489 if (found_match)
490 {
491 for (size_t i = 1; i < what.size(); i += 2)
492 {
493 std::string var = what[i];
494
495 auto envVar = getenv(var.c_str());
496 if (envVar)
497 {
498 string = boost::regex_replace(string, e, std::string(envVar));
499 found = true;
500 }
501 }
502 }
503 };
504 replaceVars(e);
505 replaceVars(e2);
506 return found;
507 }
508
509 void
510 ArmarXDataPath::ReplaceVar(std::string& string,
511 const std::string varName,
512 const std::string& varValue)
513 {
514 string = simox::alg::replace_all(string, std::string("${") + varName + "}", varValue);
515 }
516
517 void
519 {
520 ReplaceEnvVars(path);
521 if (!path.empty() && path[0] == '~')
522 {
523 path = path.erase(0, 1);
524 auto envVar = getenv("HOME");
525 if (envVar)
526 {
527 path = std::string(envVar) + "/" + path;
528 }
529 else
530 {
531 ARMARX_WARNING << "$HOME var is not set!";
532 }
533 }
534 path = cleanPath(path);
535 }
536
537 std::string
538 ArmarXDataPath::resolvePath(const std::string& path, bool verbose)
539 {
540 std::string resolved = path;
541 ResolveHomePath(resolved);
542 if (fs::path(resolved).is_relative())
543 {
544 std::string absolute;
545 if (getAbsolutePath(resolved, absolute, {}, verbose))
546 {
547 resolved = absolute;
548 }
549 }
550 return resolved;
551 }
552
553 void
554 ArmarXDataPath::addDataPaths(const std::string& dataPathList)
555 {
556 init();
557 __addPaths(dataPathList);
558 }
559
560 void
561 ArmarXDataPath::addDataPaths(const std::vector<std::string>& dataPathList)
562 {
563 init();
564 for (const auto& p : dataPathList)
565 {
566 __addPaths(p);
567 }
568 }
569
570 void
571 ArmarXDataPath::addDataPath(const std::string& dataPath)
572 {
573 init();
574 __addPaths(dataPath);
575 }
576
577 std::string
579 {
580 if (const char* home_path = std::getenv("ArmarXHome_DIR"))
581 {
582 return cleanPath(std::string(home_path));
583 }
584 return std::string();
585 }
586
587 void
588 ArmarXDataPath::init()
589 {
590 if (ArmarXDataPath_data.initialized)
591 {
592 return;
593 }
594
595 // printf("ArmarXDataPath::init(), this=%p\n", (void*)&ArmarXDataPath_data);
596 // printBacktrace();
597
598 if (const char* data_path = std::getenv("ArmarXData_DIRS"))
599 {
600 std::string pathStr(data_path);
601 __addPaths(pathStr);
602 }
603
604 //check the documented variable
605 if (const char* data_path_dir = std::getenv("ArmarXData_DIR"))
606 {
607 std::string pathStr(data_path_dir);
608 __addPaths(pathStr);
609 }
610
611 ArmarXDataPath_data.initialized = true;
612 }
613
614 std::vector<std::string>
616 {
617 return ArmarXDataPath_data.dataPaths;
618 }
619
620 bool
621 ArmarXDataPath::__addPaths(const std::string& pathList)
622 {
623 if (pathList == "")
624 {
625 return false;
626 }
627
628 std::vector<std::string> separatedPaths = __separatePaths(pathList);
629
630 if (separatedPaths.size() == 0)
631 {
632 return false;
633 }
634
635 bool ok = true;
636
637 for (int i = separatedPaths.size() - 1; i >= 0; i--)
638 {
639 ArmarXDataPath::ReplaceEnvVars(separatedPaths[i]);
640 ok = ok & __addPath(separatedPaths[i]);
641 }
642
643 return ok;
644 }
645
646 std::vector<std::string>
647 ArmarXDataPath::__separatePaths(const std::string& pathList)
648 {
649 std::string delimiters = ";";
650 std::vector<std::string> tokens = simox::alg::split(pathList, delimiters);
651 return tokens;
652 }
653
654 bool
655 ArmarXDataPath::__pathIsValid(const std::string& path)
656 {
657 if (path.empty())
658 {
659 return false;
660 }
661
662 std::filesystem::path p(path);
663 return std::filesystem::is_directory(p) || std::filesystem::is_symlink(p);
664 }
665
666 bool
667 ArmarXDataPath::__addPath(const std::string& path)
668 {
669 if (path.empty())
670 {
671 return false;
672 }
673
674 std::vector<std::string> splitted = simox::alg::split(path, "/");
675
676 if (splitted.size() < 3)
677 {
678 ARMARX_WARNING_S << "Not a valid data path: '" << path << "'" << std::endl;
679 return false;
680 }
681
682 std::string root = "";
683 std::string project = splitted[splitted.size() - 2];
684 std::string data = splitted[splitted.size() - 1];
685
686 for (unsigned int i = 0; i < splitted.size() - 2; ++i)
687 {
688 root += "/" + splitted[i];
689 }
690
691 std::filesystem::path p(root + "/" + project + "/" + data);
692
693 if (!__pathIsValid(p))
694 {
695 ARMARX_INFO_S << "Not a valid data path: '" << p
696 << "'. Try to capitalize project folder..." << std::endl;
697
698 // also check for capitalized parent folder (usually the project)
699 project = simox::alg::capitalize_words(project);
700 p = std::filesystem::path(root + "/" + project + "/" + data);
701 if (!__pathIsValid(p))
702 {
703 ARMARX_INFO_S << "Not a valid data path: '" << p
704 << "'. Try to caps project folder..." << std::endl;
705
706 // also check for caps parent folder (usually the project)
707 project = simox::alg::to_upper(project);
708 p = std::filesystem::path(root + "/" + project + "/" + data);
709
710 if (!__pathIsValid(p))
711 {
712 ARMARX_WARNING_S << "Not a valid data path: '" << p << "'" << std::endl;
713 return false;
714 }
715 }
716 }
717
718 if (std::find(ArmarXDataPath_data.dataPaths.begin(),
719 ArmarXDataPath_data.dataPaths.end(),
720 p) == ArmarXDataPath_data.dataPaths.end())
721 {
722 ARMARX_DEBUG_S << "Adding data path:" << p << std::endl;
723 ArmarXDataPath_data.dataPaths.push_back(p);
724 }
725 return true;
726 }
727
728 std::string
730 {
731 try
732 {
734 if (application.get() != nullptr)
735 {
736
737 std::string cachePathStr;
738
739 cachePathStr = application->getProperty<std::string>("CachePath").getValue();
740 if (std::filesystem::path(cachePathStr).is_relative())
741 {
742 std::string pathPrefix;
743 if (getenv(Application::ArmarXUserConfigDirEnvVar.c_str()))
744 {
745 pathPrefix =
746 std::string(getenv(Application::ArmarXUserConfigDirEnvVar.c_str()));
747 }
748 else
749 {
751 }
752 // ARMARX_INFO << VAROUT(pathPrefix);
753 cachePathStr =
754 (std::filesystem::path(pathPrefix) / std::filesystem::path(cachePathStr))
755 .string();
756 }
757 else
758 {
759 // ARMARX_INFO << "Cache path is absolute: " << cachePathStr;
760 }
761
762 ReplaceEnvVars(cachePathStr);
763 return cachePathStr;
764 }
765 else
766 {
767 return "";
768 }
769 }
770 catch (LocalException& error)
771 {
772 return "";
773 }
774 }
775
776 std::string
778 {
779 char* env_armarx_workspace = getenv("ARMARX_WORKSPACE");
780 char* env_armarx_default_config_dir_name = getenv("ARMARX_CONFIG_DIR_NAME");
781
782 std::filesystem::path armarx_workspace;
783 std::filesystem::path armarx_config_dir;
784
785 if (env_armarx_workspace != nullptr)
786 {
787 armarx_workspace = std::filesystem::path(env_armarx_workspace);
788 }
789 else
790 {
791 char* home = getenv("HOME");
792
793 if (home != nullptr)
794 {
795 armarx_workspace = std::filesystem::path(home);
796 }
797 else
798 {
799 armarx_workspace = "~/";
800 }
801 }
802
803 if (env_armarx_default_config_dir_name != nullptr)
804 {
805 armarx_config_dir = std::filesystem::path(env_armarx_default_config_dir_name);
806 }
807 else
808 {
809 if (env_armarx_workspace != nullptr)
810 {
811 armarx_config_dir = "armarx_config";
812 }
813 // Legacy mode.
814 else
815 {
816 armarx_config_dir = ".armarx";
817 }
818 }
819
820 return (armarx_workspace / armarx_config_dir).string();
821 }
822
823 bool
824 ArmarXDataPath::FindPackageAndAddDataPath(const std::string& packageName)
825 {
826 if (packageName.empty())
827 {
828 return false;
829 }
830 armarx::CMakePackageFinder finder(packageName);
831 if (finder.packageFound())
832 {
834 return true;
835 }
836 return false;
837 }
838} // namespace armarx
uint8_t data[1]
#define VAROUT(x)
static ApplicationPtr getInstance()
Retrieve shared pointer to the application object.
static const std::string ArmarXUserConfigDirEnvVar
static std::string GetArmarXConfigDefaultPath(bool envVarExpanded=true)
static std::string cleanPath(const std::string &filepathStr)
static bool mergePaths(std::string path, std::string subPath, std::string &result)
static std::string relativeTo(const std::string &from, const std::string &to)
Transform an absolute filepath into a relative path of the other absolute filepath.
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
static bool SearchReadableFile(const std::string &querryFileName, std::string &resultFileName, bool verbose=true)
static void addDataPath(const std::string &dataPath)
static void ResolveHomePath(std::string &path)
Resolves a path like ~/myfile.txt or $HOME/myfile.txt to /home/user/myfile.txt.
static std::string getProject(const std::vector< std::string > &projects, const std::string &relativeFilename)
static std::string getRelativeArmarXPath(const std::string &absolutePathString)
This method tries to morph a given absolute path into a relative path to a ArmarXDataPath.
static void initDataPaths(const std::string &dataPathList)
static std::string getHomePath()
static bool ReplaceEnvVars(std::string &string)
ReplaceEnvVars replaces environment variables in a string with their values, if the env.
static std::string GetDefaultUserConfigPath()
The user config directory of ArmarX.
static void ReplaceVar(std::string &string, const std::string varName, const std::string &varValue)
Replaces all occurences of variables in bash notation, e.g.
static std::vector< std::string > getDataPaths()
static void addDataPaths(const std::string &dataPathList)
static std::string resolvePath(const std::string &path, bool verbose=true)
Resolves environment variables and home paths and tries to make path absolute.
static std::string GetCachePath()
The base Cache directory of ArmarX.
static bool FindPackageAndAddDataPath(const std::string &packageName)
Search for the package and add its data path if it was found.
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
bool packageFound() const
Returns whether or not this package was found with cmake.
#define ARMARX_DEBUG_S
The logging level for output that is only interesting while debugging.
Definition Logging.h:205
#define ARMARX_INFO_S
Definition Logging.h:202
#define ARMARX_VERBOSE_S
Definition Logging.h:207
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:213
void project(pcl::PointCloud< pcl::PointXYZ > &cloud, wykobi::Polygon polygon)
This file offers overloads of toIce() and fromIce() functions for STL container types.
fs::path remove_trailing_separator(fs::path p)
Definition filesystem.h:34
IceUtil::Handle< Application > ApplicationPtr
Definition Application.h:93
bool Contains(const ContainerType &container, const ElementType &searchElement)
Definition algorithm.h:330
std::vector< std::string > dataPaths