ObjectMemory.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 RobotAPI::ArmarXObjects::ObjectMemory
17  * @author Rainer Kartmann ( rainer dot kartmann 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 "ObjectMemory.h"
24 
25 #include <VirtualRobot/VirtualRobot.h>
26 
31 
36 #include <RobotAPI/libraries/armem_objects/aron/Marker.aron.generated.h>
37 #include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
39 
41 {
42 
45  {
48 
49  const std::string prefix = "mem.";
51 
52  classSegment.defineProperties(defs, prefix + "cls.");
53  instance::SegmentAdapter::defineProperties(defs, prefix + "inst.");
54  familiar_object_instance::SegmentAdapter::defineProperties(defs, prefix + "fam_obj_inst.");
55 
56  attachmentSegment.defineProperties(defs, prefix + "attachments.");
57 
58 
59  // Publish
60  defs->topic(debugObserver);
61 
62  // Subscribe
63  defs->topic<
64  objpose::
65  ObjectPoseTopic>(); // "ObjectPoseTopic", "ObjectPoseTopicName", "Name of the Object Pose Topic.");
66 
67  // Use
68  // defs->component(kinematicUnitObserver); // Optional dependency.
69  defs->defineOptionalProperty<std::string>("cmp.KinematicUnitObserverName",
70  "KinematicUnitObserver",
71  "Name of the kinematic unit observer.");
72  defs->optional(predictionTimeWindow,
73  "prediction.TimeWindow",
74  "Duration of time window into the past to use for predictions"
75  " when requested via the PredictingMemoryInterface (in seconds).");
76 
77  defs->optional(p.markerMemoryName, prefix + ".marker.Name", "Marker Memory Name");
78  defs->optional(p.maxMarkerHistorySize,
79  prefix + ".marker.maxHistorySize",
80  "Maximum marker memory history size");
81 
82  return defs;
83  }
84 
86  instance::SegmentAdapter(iceAdapter()),
87  familiar_object_instance::SegmentAdapter(iceAdapter()),
88  classSegment(iceAdapter()),
89  attachmentSegment(iceAdapter()),
90  virtualRobotReaderPlugin(nullptr)
91  {
92  addPlugin(virtualRobotReaderPlugin);
93  }
94 
96  {
97  }
98 
99  std::string
101  {
102  return "ObjectMemory";
103  }
104 
105  void
107  {
108  const auto initSegmentWithCatch = [&](const std::string& segmentName, const auto&& fn)
109  {
110  try
111  {
112  fn();
113  }
114  catch (const LocalException& e)
115  {
116  ARMARX_ERROR << "Failed to init `" << segmentName << "` segment. Reason: \n"
117  << e.what();
118  }
119  catch (const std::exception& e)
120  {
121  ARMARX_ERROR << "Failed to init `" << segmentName << "` segment. Reason: \n"
122  << e.what();
123  }
124  catch (...)
125  {
126  ARMARX_ERROR << "Failed to init `" << segmentName
127  << "` segment for unknown reason.";
128  }
129  };
130 
131  // Class segment needs to be initialized before instance segment,
132  // as the instance segment may refer to and search through the class segment.
133  initSegmentWithCatch("class", [&]() { classSegment.init(); });
134 
137 
138  initSegmentWithCatch("attachment", [&]() { attachmentSegment.init(); });
139 
140  initSegmentWithCatch(p.markerMemoryName,
141  [&]()
142  {
143  workingMemory()
144  .addCoreSegment(p.markerMemoryName,
145  arondto::Marker::ToAronType())
146  .setMaxHistorySize(p.maxMarkerHistorySize);
147  });
148  }
149 
150  void
152  {
153  ARMARX_CHECK_NOT_NULL(virtualRobotReaderPlugin);
154 
156  kinematicUnitObserver, "cmp.KinematicUnitObserverName", false, "", false);
157 
158  // Create first to use the original values.
160 
161  // ARMARX_CHECK(virtualRobotReaderPlugin->isAvailable());
162 
163  instance::SegmentAdapter::connect(&virtualRobotReaderPlugin->get(),
164  kinematicUnitObserver,
166  debugObserver);
167 
169  std::experimental::make_observer(&virtualRobotReaderPlugin->get()),
171  debugObserver);
172 
174 
175  attachmentSegment.connect();
176 
178  }
179 
180  void
182  {
183  }
184 
185  void
187  {
188  }
189 
190  armem::actions::GetActionsOutputSeq
191  ObjectMemory::getActions(const armem::actions::GetActionsInputSeq& inputs)
192  {
193  using namespace armem::actions;
194  GetActionsOutputSeq outputs;
195  for (const auto& input : inputs)
196  {
197  auto memoryID = armarx::fromIce<armem::MemoryID>(input.id);
198  if (armem::contains(armem::MemoryID("Object", "Class"), memoryID) and
200  {
201  Menu menu{
202  Action{"vis", "Visualize object"},
203  };
204  // For strange C++ reasons, this works, but emplace_back doesn't.
205  outputs.push_back({menu.toIce()});
206  }
207  }
208 
209  return outputs;
210  }
211 
212  armem::actions::ExecuteActionOutputSeq
213  ObjectMemory::executeActions(const armem::actions::ExecuteActionInputSeq& inputs)
214  {
215  using namespace armem::actions;
216  ExecuteActionOutputSeq outputs;
217 
218  for (const auto& input : inputs)
219  {
220  auto memoryID = armarx::fromIce<armem::MemoryID>(input.id);
221  if (input.actionPath == ActionPath{"vis"})
222  {
223  if (armem::contains(armem::MemoryID("Object", "Class"), memoryID) and
225  {
226  classSegment.visualizeClass(memoryID);
227  outputs.emplace_back(true, "");
228  }
229  else
230  {
231  std::stringstream sstream;
232  sstream << "MemoryID " << memoryID
233  << " does not refer to a valid object class.";
234  outputs.emplace_back(false, sstream.str());
235  }
236  }
237  else
238  {
239  std::stringstream sstream;
240  sstream << "Action path " << input.actionPath << " is not defined.";
241  outputs.emplace_back(false, sstream.str());
242  }
243  }
244  return outputs;
245  }
246 
247  armem::prediction::data::PredictionResultSeq
248  ObjectMemory::predict(const armem::prediction::data::PredictionRequestSeq& requests)
249  {
250  std::vector<armem::prediction::data::PredictionResult> results;
251  for (const auto& request : requests)
252  {
253  auto boRequest = armarx::fromIce<armem::PredictionRequest>(request);
255  result.snapshotID = boRequest.snapshotID;
256  if (armem::contains(workingMemory().id().withCoreSegmentName("Instance"),
257  boRequest.snapshotID) and
258  not boRequest.snapshotID.hasGap() and boRequest.snapshotID.hasTimestamp())
259  {
260  objpose::ObjectPosePredictionRequest objPoseRequest;
261  toIce(objPoseRequest.timeWindow, Duration::SecondsDouble(predictionTimeWindow));
262  objPoseRequest.objectID = toIce(ObjectID(request.snapshotID.entityName));
263  objPoseRequest.settings = request.settings;
264  toIce(objPoseRequest.timestamp, boRequest.snapshotID.timestamp);
265 
266  objpose::ObjectPosePredictionResult objPoseResult =
267  predictObjectPoses({objPoseRequest}).at(0);
268  result.success = objPoseResult.success;
269  result.errorMessage = objPoseResult.errorMessage;
270 
271  if (objPoseResult.success)
272  {
274  builder.latestEntitySnapshot(boRequest.snapshotID);
275  auto queryResult = armarx::fromIce<armem::client::QueryResult>(
276  query(builder.buildQueryInputIce()));
277  std::string instanceError =
278  "Could not find instance '" + boRequest.snapshotID.str() + "' in memory";
279  if (!queryResult.success)
280  {
281  result.success = false;
282  result.errorMessage << instanceError << ":\n" << queryResult.errorMessage;
283  }
284  else
285  {
286  if (not boRequest.snapshotID.hasInstanceIndex())
287  {
288  boRequest.snapshotID.instanceIndex = 0;
289  }
290  auto* aronInstance = queryResult.memory.findLatestInstance(
291  boRequest.snapshotID, boRequest.snapshotID.instanceIndex);
292  if (aronInstance == nullptr)
293  {
294  result.success = false;
295  result.errorMessage << instanceError << ": No latest instance found.";
296  }
297  else
298  {
299  auto instance =
300  armem::arondto::ObjectInstance::FromAron(aronInstance->data());
302  instance.pose,
303  armarx::fromIce<objpose::ObjectPose>(objPoseResult.prediction));
304  result.prediction = instance.toAron();
305  }
306  }
307  }
308  }
309  else
310  {
311  result.success = false;
312  result.errorMessage << "No predictions are supported for MemoryID "
313  << boRequest.snapshotID;
314  }
315  results.push_back(result.toIce());
316  }
317 
318  return results;
319  }
320 
321  void
323  {
324  using namespace armarx::RemoteGui::Client;
325 
326  tab.reset(new RemoteGuiTab);
327 
328  tab->instance.setup(*this);
329  tab->clazz.setup(classSegment);
330 
331  HBoxLayout segments = {tab->instance.group, tab->clazz.group};
332  VBoxLayout root = {segments, VSpacer()};
333  RemoteGui_createTab(Component::getName(), root, tab.get());
334  }
335 
336  void
338  {
339  tab->instance.update(*this);
340  tab->clazz.update(classSegment);
341 
342  if (tab->clazz.data.rebuild)
343  {
345  }
346  }
347 
348  void
349  ObjectMemory::reloadKnownObjectClasses(const Ice::Current& current)
350  {
351  ARMARX_INFO << "Reloading object classes ...";
352  classSegment.reloadObjectClassesByObjectFinder();
353  ARMARX_INFO << "Reloaded object classes.";
354  }
355 
356 
357 } // namespace armarx::armem::server::obj
armarx::armem::server::obj::familiar_object_instance::SegmentAdapter::connect
void connect(std::experimental::observer_ptr< robot_state::VirtualRobotReader > virtualRobotReader, viz::Client arviz, DebugObserverInterfacePrx debugObserver)
Definition: SegmentAdapter.cpp:87
armarx::armem::server::obj::ObjectMemory::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: ObjectMemory.cpp:186
memory_ids.h
armarx::armem::server::obj::clazz::Segment::reloadObjectClassesByObjectFinder
void reloadObjectClassesByObjectFinder()
Definition: Segment.cpp:65
armarx::armem::server::obj::ObjectMemory::executeActions
armem::actions::ExecuteActionOutputSeq executeActions(const armem::actions::ExecuteActionInputSeq &inputs) override
Definition: ObjectMemory.cpp:213
armarx::ArVizComponentPluginUser::getArvizClient
armarx::viz::Client & getArvizClient()
Definition: ArVizComponentPlugin.h:45
armarx::armem::server::obj::instance::SegmentAdapter::predictObjectPoses
virtual objpose::ObjectPosePredictionResultSeq predictObjectPoses(const objpose::ObjectPosePredictionRequestSeq &requests, ICE_CURRENT_ARG) override
Definition: SegmentAdapter.cpp:444
armarx::armem::server::obj::ObjectMemory::getDefaultName
std::string getDefaultName() const override
Definition: ObjectMemory.cpp:100
armarx::armem::server::obj::ObjectMemory::getActions
armem::actions::GetActionsOutputSeq getActions(const armem::actions::GetActionsInputSeq &inputs) override
Definition: ObjectMemory.cpp:191
armarx::armem::PredictionResult::snapshotID
armem::MemoryID snapshotID
Definition: Prediction.h:62
ice_conversions.h
armarx::armem::server::plugins::ReadWritePluginUser::query
virtual armem::query::data::Result query(const armem::query::data::Input &input, const Ice::Current &=Ice::emptyCurrent) override
Definition: ReadWritePluginUser.cpp:56
query.h
armarx::armem::server::obj::ObjectMemory::ObjectMemory
ObjectMemory()
Definition: ObjectMemory.cpp:85
armarx::RemoteGui::Client::VBoxLayout
Definition: Widgets.h:167
armarx::armem::attachment::ObjectID
armem::MemoryID ObjectID
Definition: types.h:79
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
Prediction.h
armarx::armem::server::obj::instance::SegmentAdapter::init
void init()
Definition: SegmentAdapter.cpp:66
armarx::armem::toIce
void toIce(data::MemoryID &ice, const MemoryID &id)
Definition: ice_conversions.cpp:20
std::experimental::fundamentals_v2::make_observer
observer_ptr< _Tp > make_observer(_Tp *__p) noexcept
armarx::armem::server::obj::ObjectMemory::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: ObjectMemory.cpp:151
armarx::armem::base::MemoryBase::name
std::string & name()
Definition: MemoryBase.h:92
ice_conversions.h
armarx::ManagedIceObject::addPlugin
PluginT * addPlugin(const std::string prefix="", ParamsT &&... params)
Definition: ManagedIceObject.h:186
armarx::armem::client::query::Builder::latestEntitySnapshot
void latestEntitySnapshot(const MemoryID &entityID)
Definition: Builder.cpp:131
armarx::armem::PredictionResult
Definition: Prediction.h:57
armarx::armem::contains
bool contains(const MemoryID &general, const MemoryID &specific)
Indicates whether general is "less specific" than, or equal to, specific, i.e.
Definition: MemoryID.cpp:563
armarx::armem::server::plugins::ReadWritePluginUser::workingMemory
server::wm::Memory & workingMemory()
Definition: ReadWritePluginUser.cpp:106
armarx::armem::server::obj
Definition: ObjectMemory.cpp:40
armarx::RemoteGui::Client::VSpacer
Definition: Widgets.h:204
armarx::armem::server::obj::ObjectMemory::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: ObjectMemory.cpp:181
Clock.h
armarx::armem::server::obj::clazz::Segment::init
void init() override
Definition: Segment.cpp:53
armarx::armem::objects::memoryID
const MemoryID memoryID
Definition: memory_ids.cpp:28
armarx::Component::getProxyFromProperty
ProxyType getProxyFromProperty(const std::string &propertyName, bool addToDependencies=false, const std::string &endpoints="", bool throwOnProxyError=true)
Get a proxy whose name is specified by the given property.
Definition: Component.h:242
armarx::armem::client::query::Builder::buildQueryInputIce
armem::query::data::Input buildQueryInputIce() const
Definition: Builder.cpp:21
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
ManagedIceObject.h
armarx::armem::PredictionResult::prediction
aron::data::DictPtr prediction
Definition: Prediction.h:63
armarx::aron::input
ReaderT::InputType & input
Definition: rw.h:12
armarx::armem::server::obj::familiar_object_instance::SegmentAdapter::init
void init()
Definition: SegmentAdapter.cpp:76
armarx::core::time::Duration::SecondsDouble
static Duration SecondsDouble(double seconds)
Constructs a duration in seconds.
Definition: Duration.cpp:78
armarx::objpose::toAron
void toAron(arondto::ObjectAttachmentInfo &dto, const ObjectAttachmentInfo &bo)
Definition: objpose.cpp:21
armarx::armem::server::obj::clazz::Segment::defineProperties
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="") override
Definition: Segment.cpp:38
armarx::armem::PredictionResult::toIce
armem::prediction::data::PredictionResult toIce() const
Definition: Prediction.cpp:74
armarx::armem::server::obj::attachments::Segment::init
void init()
Definition: Segment.cpp:44
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::armem::MemoryID::hasGap
bool hasGap() const
Indicate whether this ID has a gap such as in 'Memory//MyProvider' (no core segment name).
Definition: MemoryID.cpp:163
armarx::armem::server::obj::ObjectMemory::predict
armem::prediction::data::PredictionResultSeq predict(const armem::prediction::data::PredictionRequestSeq &requests) override
Definition: ObjectMemory.cpp:248
armarx::armem::server::obj::ObjectMemory::reloadKnownObjectClasses
void reloadKnownObjectClasses(const Ice::Current &current) override
Definition: ObjectMemory.cpp:349
armarx::armem::MemoryID::hasEntityName
bool hasEntityName() const
Definition: MemoryID.h:121
armarx::armem::MemoryID::memoryName
std::string memoryName
Definition: MemoryID.h:50
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_startRunningTask
void RemoteGui_startRunningTask()
Definition: LightweightRemoteGuiComponentPlugin.cpp:119
armarx::RemoteGui::Client::HBoxLayout
Definition: Widgets.h:160
ObjectMemory.h
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
armarx::armem::server::obj::attachments::Segment::defineProperties
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="")
Definition: Segment.cpp:33
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:69
armarx::armem::PredictionResult::errorMessage
std::string errorMessage
Definition: Prediction.h:60
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::armem::server::obj::attachments::Segment::connect
void connect()
Definition: Segment.cpp:54
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::armem::index::memoryID
const MemoryID memoryID
Definition: memory_ids.cpp:28
armarx::armem::server::obj::ObjectMemory::createRemoteGuiTab
void createRemoteGuiTab()
Definition: ObjectMemory.cpp:322
armarx::armem::server::obj::clazz::Segment::connect
void connect(viz::Client arviz)
Definition: Segment.cpp:80
armarx::armem::client::query::Builder
The query::Builder class provides a fluent-style specification of hierarchical queries.
Definition: Builder.h:21
ice_conversions_templates.h
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:108
armarx::armem::PredictionResult::success
bool success
Definition: Prediction.h:59
armarx::armem::server::obj::ObjectMemory::~ObjectMemory
virtual ~ObjectMemory() override
Definition: ObjectMemory.cpp:95
armarx::armem::server::obj::ObjectMemory::RemoteGui_update
void RemoteGui_update() override
Definition: ObjectMemory.cpp:337
armarx::armem::server::obj::familiar_object_instance::SegmentAdapter::defineProperties
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="")
Definition: SegmentAdapter.cpp:69
armarx::RemoteGui::Client
Definition: EigenWidgets.cpp:8
armarx::armem::server::obj::ObjectMemory::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: ObjectMemory.cpp:106
aron_conversions.h
armarx::armem::server::obj::ObjectMemory::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: ObjectMemory.cpp:44
armarx::armem::server::obj::instance::SegmentAdapter::connect
void connect(robot_state::VirtualRobotReader *virtualRobotReader, KinematicUnitObserverInterfacePrx kinematicUnitObserver, viz::Client arviz, DebugObserverInterfacePrx debugObserver)
Definition: SegmentAdapter.cpp:78
armarx::armem::server::obj::instance::SegmentAdapter::defineProperties
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="")
Definition: SegmentAdapter.cpp:57