Component.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 Navigation::ArmarXObjects::ControlMemory
17  * @author Fabian Reister ( fabian dot reister at kit dot edu )
18  * @date 2021
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "Component.h"
24 
25 // STD / STL
26 #include <filesystem>
27 #include <fstream>
28 #include <iostream>
29 
35 
42 
45 // #include <armarx/navigation/algorithms/Costmap.h>
46 // #include <armarx/navigation/memory/constants.h>
47 // #include <armarx/navigation/algorithms/aron/Costmap.aron.generated.h>
48 // #include <armarx/navigation/core/Graph.h>
49 // #include <armarx/navigation/core/aron/Graph.aron.generated.h>
50 // #include <armarx/navigation/core/aron/Location.aron.generated.h>
51 // #include <armarx/navigation/core/aron/Trajectory.aron.generated.h>
52 // #include <armarx/navigation/core/aron/Twist.aron.generated.h>
53 // #include <armarx/navigation/graph/constants.h>
54 // #include <armarx/navigation/location/constants.h>
55 
56 #include <armarx/control/common/control_law/aron/TaskspaceImpedanceControllerConfig.aron.generated.h>
57 
58 // #include <armarx/control/njoint_qp_controller/aron_conversions.h>
59 
60 // #include <simox/control/method/examples/json_conversions.h>
61 
63 {
64 
65 
68  {
71 
72  // Publish to a topic (passing the TopicListenerPrx).
73  // def->topic(myTopicListener);
74 
75  // Subscribe to a topic (passing the topic name).
76  // def->topic<PlatformUnitListener>("MyTopic");
77 
78  // Use (and depend on) another component (passing the ComponentInterfacePrx).
79  // def->component(myComponentProxy)
80 
81 
83  def->optional(properties.snapshotToLoad,
84  "p.snapshotToLoad",
85  "Memory snapshot to load at start up \n"
86  "(e.g. 'PriorKnowledgeData/navigation-graphs/snapshot').");
87 
88  def->optional(properties.locationGraph.visuFrequency,
89  "p.locationGraph.visuFrequency",
90  "Visualization frequeny of locations and graph edges [Hz].");
91 
92  // core segment max history sizes
93  {
94  def->optional(properties.coreSeg.defaultParameterization.maxHistorySize,
95  "p.coreSeg.defaultParameterization.maxHistorySize",
96  "Max history size of the " +
99  " core segment.");
100 
101  def->optional(
102  properties.coreSeg.parameterization.maxHistorySize,
103  "p.coreSeg.defaultParameterization.maxHistorySize",
104  "Max history size of the " +
106  " core segment.");
107  }
108 
109  return def;
110  }
111 
112  void
114  {
115  // Topics and properties defined above are automagically registered.
116 
117  // Keep debug observer data until calling `sendDebugObserverBatch()`.
118  // (Requies the armarx::DebugObserverComponentPluginUser.)
119  // setDebugObserverBatchModeEnabled(true);
120 
121  workingMemory()
124  .setMaxHistorySize(properties.coreSeg.defaultParameterization.maxHistorySize);
125 
126  workingMemory()
128  .setMaxHistorySize(properties.coreSeg.parameterization.maxHistorySize);
129 
130 
131  /*
132  if (not properties.snapshotToLoad.empty())
133  {
134  std::filesystem::path snapshotToLoadPath(
135  ArmarXDataPath::resolvePath(properties.snapshotToLoad));
136  if (std::filesystem::is_directory(snapshotToLoadPath))
137  {
138  // This section loads the snapshot specified by the scenario parameters
139  // resolve the paths for the locations and graphs
140  const std::filesystem::path graph = snapshotToLoadPath / "Graph";
141  const std::filesystem::path location = snapshotToLoadPath / "Location";
142 
143  // remove date from folder name (if present)
144  // Sometimes, we use the date before the snapshotname and use a symlink to the real data (e.g. R003 and 2022-03-01_R003)
145  auto splitted = simox::alg::split(snapshotToLoadPath.filename().string(), "_");
146  ARMARX_CHECK_GREATER(splitted.size(), 0);
147  const std::string providerName = splitted[splitted.size() - 1];
148 
149  // This if statement loads the location. Each location is a single file (without extension). The filename is the name of the location.
150  // The file contains json with the globalRobotPose (4x4 matrix) and relativeToObject information
151  if (std::filesystem::is_directory(location))
152  {
153  armem::Commit c;
154  armem::MemoryID providerID = workingMemory().id();
155  providerID.coreSegmentName = "Location";
156  providerID.providerSegmentName = providerName;
157  for (const auto& subdir : std::filesystem::directory_iterator(
158  location)) // iterate over all files in folder (the locations)
159  {
160  const std::filesystem::path location = subdir.path();
161  if (std::filesystem::is_regular_file(
162  location)) // check if its a file (otherwise skip)
163  {
164  std::ifstream ifs(location);
165  const std::string content((std::istreambuf_iterator<char>(ifs)),
166  (std::istreambuf_iterator<char>()));
167 
168  // parse location as json. All files in Location folder must be valid json objects!
169  nlohmann::json j = nlohmann::json::parse(content);
170 
171  if (j.find("globalRobotPose") == j.end())
172  {
173  ARMARX_WARNING
174  << "The file '" << location.string()
175  << "' has no 'globalRobotPose' member. Skipping this file.";
176  continue;
177  }
178 
179  if (j.find("relativeToObject") == j.end())
180  {
181  ARMARX_WARNING
182  << "The file '" << location.string()
183  << "' has no 'relativeToObject' member. Skipping this file.";
184  continue;
185  }
186 
187  std::vector<float> p = j.at("globalRobotPose");
188  ARMARX_CHECK_EQUAL(p.size(), 16);
189 
190  navigation::location::arondto::Location loc;
191  loc.globalRobotPose << p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
192  p[8], p[9], p[10], p[11], p[12], p[13], p[14],
193  p[15]; // load the 4x4 matrix
194 
195  // TODO: All location I have seen were null.
196  // I don't know how this member should look like (von @Fabian Peller to @Fabian Reister)
197  loc.relativeToObject = std::nullopt;
198 
199  // send commit to memory
200  auto& up = c.add();
201  up.confidence = 1.0;
202  up.referencedTime = armem::Time::Now();
203  up.timeSent = armem::Time::Now();
204  up.timeArrived = armem::Time::Now();
205  up.entityID = providerID.withEntityName(location.filename().string());
206  up.instancesData = {loc.toAron()};
207  }
208  }
209 
210  // commit all locations at once
211  iceAdapter().commit(c);
212  }
213 
214  // Next we load the graphs. The graph folder may contain several graphs, represented by different folders.
215  // Each of those graphs contains a list of files representing the vertices. The filename is the vertice id (ideally starting at 0).
216  // The file contains a json with the corresponding location name (as path) and the adjacent vertives (representing the directed outgoing edges).
217  if (std::filesystem::is_directory(graph))
218  {
219  armem::Commit c;
220  armem::MemoryID providerID = workingMemory().id();
221  providerID.coreSegmentName = memory::constants::GraphCoreSegmentName;
222  providerID.providerSegmentName = providerName;
223 
224  for (const auto& graphdir : std::filesystem::directory_iterator(
225  graph)) // iterate over the different graphs (subfolders)
226  {
227  const std::filesystem::path singleGraph = graphdir.path();
228  if (std::filesystem::is_directory(
229  singleGraph)) // assure that its a folder. otherwise skip
230  {
231  navigation::core::arondto::Graph g;
232 
233  for (const auto& subdir : std::filesystem::directory_iterator(
234  singleGraph)) // iterate over all files in the graph
235  {
236  const std::filesystem::path vertice = subdir.path();
237  if (std::filesystem::is_regular_file(
238  vertice)) // assure its a file. otherwise skip
239  {
240  std::ifstream ifs(vertice);
241  const std::string content((std::istreambuf_iterator<char>(ifs)),
242  (std::istreambuf_iterator<char>()));
243 
244  // parse vertice. Each vertice must be a valid json object
245  nlohmann::json j = nlohmann::json::parse(content);
246  if (j.find("location") == j.end())
247  {
248  ARMARX_WARNING
249  << "The file '" << vertice.string()
250  << "' has no 'location' member. Skipping this file.";
251  continue;
252  }
253 
254  if (j.find("outgoingEdges") == j.end())
255  {
256  ARMARX_WARNING << "The file '" << vertice.string()
257  << "' has no 'outgoingEdges' member. "
258  "Skipping this file.";
259  continue;
260  }
261 
262  std::string location = j.at("location");
263  int id = std::stoi(vertice.filename());
264 
265  auto split = simox::alg::split(location, "/");
266  ARMARX_CHECK_EQUAL(
267  split.size(),
268  4); // the location is always a path like Navigation/Location/XXX/YYY
269 
270  armarx::control::core::arondto::Vertex v;
271  v.vertexID = id;
272  v.locationID.memoryName = split[0];
273  v.locationID.coreSegmentName = split[1];
274  v.locationID.providerSegmentName = split[2];
275  v.locationID.entityName = split[3];
276  toAron(v.locationID.timestamp, armem::Time::Invalid());
277  v.locationID.instanceIndex = 0;
278 
279  g.vertices.push_back(v);
280 
281  // add edges of this vertice to graph
282  std::vector<float> edges = j.at("outgoingEdges");
283 
284  for (const auto edge_id : edges)
285  {
286  armarx::control::core::arondto::Edge e;
287  e.sourceVertexID = id;
288  e.targetVertexID = edge_id;
289  g.edges.push_back(e);
290  }
291  }
292  }
293 
294  auto& up = c.add();
295  up.confidence = 1.0;
296  up.referencedTime = armem::Time::Now();
297  up.timeSent = armem::Time::Now();
298  up.timeArrived = armem::Time::Now();
299  up.entityID =
300  providerID.withEntityName(singleGraph.filename().string());
301  up.instancesData = {g.toAron()};
302  }
303  }
304 
305  // send graph to memory
306  iceAdapter().commit(c);
307  }
308 
309  // LEGACY CODE (Not working anymore since the wm json export changed due to ltm updates and aron updates)
310  // armem::wm::Memory memory = armem::server::ltm::disk::load(path.value());
311  //armem::server::ltm::disk::Memory ltm(path.value());
312  //armem::wm::Memory memory;
313  //ltm.loadAll(memory);
314  //workingMemory().update(armem::toCommit(memory));
315  ARMARX_INFO << "Loaded ControlMemory '" << properties.snapshotToLoad << "'";
316  }
317  else
318  {
319  ARMARX_WARNING << "Could not load ControlMemory '" << properties.snapshotToLoad
320  << "'. Continue with empty memory.";
321  }
322  }
323  */
324 
325  loadDefaultConfigs();
326  }
327 
328  void
329  Component::loadDefaultConfigs()
330  {
331  // std::string filename;
332  // ArmarXDataPath::getAbsolutePath("armarx_control/controller_config/default/"
333  // "njoint_controller/impedance_controller_config.json",
334  // filename);
335 
336  // std::ifstream ifs{filename};
337 
338  // nlohmann::json defaultConfig;
339  // ifs >> defaultConfig;
340 
341  // {
342 
343  // common::control_law::arondto::TaskSpaceImpedanceControllerConfig cfg;
344  // // TODO load
345 
346  // armem::Commit c;
347  // armem::MemoryID providerID = workingMemory().id();
348  // providerID.coreSegmentName = memory::constants::DefaultParameterizationCoreSegmentName;
349  // providerID.providerSegmentName =
350  // common::ControllerTypeNames.to_name(common::ControllerType::TSImp);
351 
352 
353  // auto& up = c.add();
354  // up.confidence = 1.0;
355  // up.referencedTime = up.timeSent = up.timeArrived = armem::Time::Now();
356 
357  // up.entityID = providerID.withEntityName("default");
358  // up.instancesData = {cfg.toAron()};
359 
360  // iceAdapter().commit(c);
361  // }
362 
363  // {
364  // njoint_qp_controller::impedance::arondto::WholeBodyImpedanceControllerConfig cfg;
365 
366  // // "kpImpedance": [300, 300, 300, 3, 3, 3],
367  // // "kdImpedance": [ 50, 50, 50, 1, 1, 1],
368  // // "kpNullspace": [25.0, 15.0, 15.0, 5.0, 5.0, 5.0, 5.0, 5.0],
369  // // "kdNullspace": [4.0, 2.0, 2.0, 1.0, 1.0, 1.0, 1.0, 2.0],
370  // // "desiredNullspaceJointAngles": [],
371  // // "torqueLimit": 20,
372  // // "qvelFilter": 0.9
373 
374 
375  // cfg.leftArmImpedanceConfig.kpImpedance << 300, 300, 300, 3, 3, 3;
376  // cfg.leftArmImpedanceConfig.kdImpedance << 50, 50, 50, 1, 1, 1;
377  // cfg.leftArmImpedanceConfig.kpNullspace << 25.0, 15.0, 15.0, 5.0, 5.0, 5.0, 5.0, 5.0;
378  // cfg.leftArmImpedanceConfig.kdNullspace << 4.0, 2.0, 2.0, 1.0, 1.0, 1.0, 1.0, 2.0;
379  // // cfg.leftArmImpedanceConfig.desiredNullspaceJointAngles;
380  // cfg.leftArmImpedanceConfig.torqueLimit = 20;
381  // cfg.leftArmImpedanceConfig.qvelFilter = 0.9;
382 
383  // cfg.rightArmImpedanceConfig = cfg.leftArmImpedanceConfig;
384 
385 
386  // // TODO load
387 
388  // armem::Commit c;
389  // armem::MemoryID providerID = workingMemory().id();
390  // providerID.coreSegmentName = memory::constants::DefaultParameterizationCoreSegmentName;
391  // providerID.providerSegmentName =
392  // common::ControllerTypeNames.to_name(common::ControllerType::QPWholeBodyImpedance);
393 
394 
395  // auto& up = c.add();
396  // up.confidence = 1.0;
397  // up.referencedTime = up.timeSent = up.timeArrived = armem::Time::Now();
398 
399  // up.entityID = providerID.withEntityName("default");
400  // up.instancesData = {cfg.toAron()};
401 
402  // iceAdapter().commit(c);
403  // }
404 
405  // CMakePackageFinder pkg_finder("armarx_control");
406  // const std::filesystem::path pkgDataDir{pkg_finder.getDataDir()};
407 
408  // const std::filesystem::path configBasePath =
409  // pkgDataDir / "armarx_control/controller_config";
410 
411  // for (auto const& dir_entry : std::filesystem::directory_iterator{
412  // configBasePath /
413  // common::ControllerTypeNames.to_name(common::ControllerType::QPWholeBodyVelocity)})
414  // {
415  // if (not dir_entry.is_regular_file())
416  // {
417  // continue;
418  // }
419 
420  // const std::string filename = dir_entry.path();
421 
422  // ARMARX_INFO << "Loading config from file `" << filename << "`";
423  // std::ifstream ifs{filename};
424 
425  // nlohmann::json jsonConfig;
426  // ifs >> jsonConfig;
427 
428  // njoint_qp_controller::velocity::WholeBodyVelocityControllerConfig cfg;
429  // cfg.params.weights = jsonConfig.at("weights");
430  // cfg.params.kinematicConstraints = jsonConfig.at("kinematicConstraints");
431 
432  // njoint_qp_controller::velocity::arondto::WholeBodyVelocityControllerConfig aronCfg;
433  // toAron(aronCfg, cfg);
434 
435 
436  // armem::Commit c;
437  // armem::MemoryID providerID = workingMemory().id();
438  // providerID.coreSegmentName = memory::constants::DefaultParameterizationCoreSegmentName;
439  // providerID.providerSegmentName =
440  // common::ControllerTypeNames.to_name(common::ControllerType::QPWholeBodyVelocity);
441 
442 
443  // auto& up = c.add();
444  // up.confidence = 1.0;
445  // up.referencedTime = up.timeSent = up.timeArrived = armem::Time::Now();
446 
447  // up.entityID = providerID.withEntityName("default");
448  // up.instancesData = {aronCfg.toAron()};
449 
450  // iceAdapter().commit(c);
451  // }
452  }
453 
454  void
456  {
457  // Do things after connecting to topics and components.
458 
459 
460  /* (Requies the armarx::DebugObserverComponentPluginUser.)
461  // Use the debug observer to log data over time.
462  // The data can be viewed in the ObserverView and the LivePlotter.
463  // (Before starting any threads, we don't need to lock mutexes.)
464  {
465  setDebugObserverDatafield("numBoxes", properties.numBoxes);
466  setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
467  sendDebugObserverBatch();
468  }
469  */
470 
471  // Setup the remote GUI.
472  {
475  }
476 
477  tasks.visuTask = new SimpleRunningTask<>([this]() { this->visuRun(); }, "Visualization");
478  tasks.visuTask->start();
479  }
480 
481  void
483  {
484  }
485 
486  void
488  {
489  }
490 
491  std::string
493  {
494  return GetDefaultName();
495  }
496 
497  std::string
499  {
500  return "ControlMemory";
501  }
502 
503  void
505  {
506  using namespace armarx::RemoteGui::Client;
507 
508  // Setup the widgets.
509  tab.locationGraph.setup(*this);
510 
511 
512  // Setup the layout.
513  VBoxLayout root = {tab.locationGraph.group, VSpacer()};
514  RemoteGui_createTab(getName(), root, &tab);
515  }
516 
517  void
519  {
520  tab.locationGraph.update(*this);
521  }
522 
523  void
525  {
526  using namespace armarx::RemoteGui::Client;
527  GridLayout grid;
528  int row = 0;
529  {
530  visuLocations.setValue(owner.properties.locationGraph.visuLocations);
531  visuGraphEdges.setValue(owner.properties.locationGraph.visuLocations);
532 
533  grid.add(Label("Visualize Locations"), {row, 0}).add(visuLocations, {row, 1});
534  ++row;
535 
536  grid.add(Label("Visualize Graph Edges"), {row, 0}).add(visuGraphEdges, {row, 1});
537  ++row;
538  }
539 
540  group = GroupBox({grid});
541  }
542 
543  void
545  {
546  if (visuLocations.hasValueChanged() or visuGraphEdges.hasValueChanged())
547  {
548  std::scoped_lock lock(owner.propertiesMutex);
549  owner.properties.locationGraph.visuLocations = visuLocations.getValue();
550  owner.properties.locationGraph.visuGraphEdges = visuGraphEdges.getValue();
551  }
552  }
553 
554  void
555  Component::visuRun()
556  {
557  // memory::Visu visu{arviz,
558  // workingMemory().getCoreSegment(navigation::location::coreSegmentID),
559  // workingMemory().getCoreSegment(navigation::graph::coreSegmentID)};
560 
561  // Properties::LocationGraph p;
562  // {
563  // std::scoped_lock lock(propertiesMutex);
564  // p = properties.locationGraph;
565  // }
566 
567  // CycleUtil cycle(static_cast<int>(1000 / p.visuFrequency));
568  // while (tasks.visuTask and not tasks.visuTask->isStopped())
569  // {
570  // {
571  // std::scoped_lock lock(propertiesMutex);
572  // p = properties.locationGraph;
573  // }
574 
575  // std::vector<viz::Layer> layers;
576 
577  // // Locations
578  // visu.drawLocations(layers, p.visuLocations);
579 
580  // // Graph Edges
581  // visu.drawGraphs(layers, p.visuGraphEdges);
582 
583  // arviz.commit(layers);
584 
585  // cycle.waitForCycleDuration();
586  // }
587  }
588 
590 
591 
592 } // namespace armarx::control::components::control_memory
armarx::SimpleRunningTask
Usage:
Definition: TaskUtil.h:85
armarx::control::memory::constants::DefaultParameterizationCoreSegmentName
const std::string DefaultParameterizationCoreSegmentName
Definition: constants.h:29
query.h
QUOTED
#define QUOTED(x)
Definition: StringHelpers.h:199
armarx::RemoteGui::Client::VBoxLayout
Definition: Widgets.h:167
armarx::control::components::control_memory::Component::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: Component.cpp:67
armarx::RemoteGui::Client::GridLayout::add
GridLayout & add(Widget const &child, Pos pos, Span span=Span{1, 1})
Definition: Widgets.cpp:438
armarx::control::components::control_memory::Component::onExitComponent
void onExitComponent() override
Definition: Component.cpp:487
armarx::control::components::control_memory::Component::onInitComponent
void onInitComponent() override
Definition: Component.cpp:113
armarx::armem::base::MemoryBase::name
std::string & name()
Definition: MemoryBase.h:92
armarx::control::memory::constants::ParameterizationCoreSegmentName
const std::string ParameterizationCoreSegmentName
Definition: constants.h:30
armarx::control::components::control_memory
Definition: Component.cpp:62
armarx::control::components::control_memory::Component::RemoteGui_update
void RemoteGui_update() override
Definition: Component.cpp:518
armarx::armem::server::plugins::ReadWritePluginUser::workingMemory
server::wm::Memory & workingMemory()
Definition: ReadWritePluginUser.cpp:106
armarx::RemoteGui::Client::VSpacer
Definition: Widgets.h:204
type.h
StringHelpers.h
armarx::control::components::control_memory::ARMARX_REGISTER_COMPONENT_EXECUTABLE
ARMARX_REGISTER_COMPONENT_EXECUTABLE(Component, Component::GetDefaultName())
json_conversions.h
armarx::control::components::control_memory::Component::onDisconnectComponent
void onDisconnectComponent() override
Definition: Component.cpp:482
memory_definitions.h
visionx::voxelgrid::Label
uint32_t Label
Type of an object label.
Definition: types.h:6
armarx::control::memory::constants::MemoryName
const std::string MemoryName
Definition: constants.h:27
armarx::RemoteGui::Client::GridLayout
Definition: Widgets.h:186
armarx::control::components::control_memory::Component::RemoteGuiTab::LocationGraph::update
void update(Component &owner)
Definition: Component.cpp:544
Component.h
armarx::RemoteGui::Client::GroupBox
Definition: Widgets.h:193
armarx::control::components::control_memory::Component::onConnectComponent
void onConnectComponent() override
Definition: Component.cpp:455
armarx::control::components::control_memory::Component
Definition: Component.h:51
armarx::armem::base::MemoryBase::addCoreSegment
CoreSegmentT & addCoreSegment(const std::string &name, aron::type::ObjectPtr coreSegmentType=nullptr, const std::vector< PredictionEngine > &predictionEngines={})
Add an empty core segment with the given name, type and prediction engines.
Definition: MemoryBase.h:259
operations.h
armarx::control::components::control_memory::Component::getDefaultName
std::string getDefaultName() const override
Definition: Component.cpp:492
aron_conversions.h
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_startRunningTask
void RemoteGui_startRunningTask()
Definition: LightweightRemoteGuiComponentPlugin.cpp:119
CycleUtil.h
Memory.h
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
Decoupled.h
constants.h
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:69
armarx::control::components::control_memory::Component::RemoteGuiTab::LocationGraph::setup
void setup(Component &owner)
Definition: Component.cpp:524
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_createTab
void RemoteGui_createTab(std::string const &name, RemoteGui::Client::Widget const &rootWidget, RemoteGui::Client::Tab *tab)
Definition: LightweightRemoteGuiComponentPlugin.cpp:103
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::control::components::control_memory::Component::GetDefaultName
static std::string GetDefaultName()
Definition: Component.cpp:498
armarx::control::memory::constants
This file is part of ArmarX.
Definition: constants.h:24
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:108
armarx::RemoteGui::Client
Definition: EigenWidgets.cpp:8
ArmarXDataPath.h
armarx::control::components::control_memory::Component::createRemoteGuiTab
void createRemoteGuiTab()
Definition: Component.cpp:504
PackagePath.h