Observer.h
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 ArmarX::Core
19 * @author Kai Welke (welke@kit.edu)
20 * @date 2011
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24 
25 #pragma once
26 
31 #include <ArmarXCore/interface/observers/VariantBase.h>
32 
33 #include <ArmarXCore/interface/observers/ObserverInterface.h>
35 
36 #include <unordered_map>
37 #include <functional>
38 #include <mutex>
39 
40 namespace armarx
41 {
42 
43  class DatafieldRef;
45 
52  {
53  public:
56  {
57  defineOptionalProperty<int>("MaxHistorySize", 5000, "Maximum number of entries in the Observer history");
58  defineOptionalProperty<float>("MaxHistoryRecordFrequency", 50.f, "The Observer history is written with this maximum frequency. Everything faster is being skipped.");
59  defineOptionalProperty<bool>("CreateUpdateFrequenciesChannel", false, "If true, an additional channel is created that shows the update frequency of every other channel in that observer.");
60 
61  }
62  };
63 
81  virtual public ObserverInterface,
82  virtual public Component
83  {
84  // ////////////////////////////////////////////////////////////////// //
85  // ice interface + local ice doubles
86  public:
87  Observer();
88 
89  ~Observer();
90 
91  std::string getObserverName() const;
92  void getObserverName_async(
93  const AMD_ObserverInterface_getObserverNamePtr& amd,
94  const Ice::Current&) const override;
95 
96  public:
106  CheckIdentifier installCheck(const CheckConfiguration& configuration);
107  void installCheck_async(
108  const AMD_ObserverInterface_installCheckPtr& amd,
109  const CheckConfiguration& configuration,
110  const Ice::Current&) override;
111 
112  public:
119  void removeCheck(const CheckIdentifier& id);
120  void removeCheck_async(
121  const AMD_ObserverInterface_removeCheckPtr& amd,
122  const CheckIdentifier& id,
123  const Ice::Current&) override;
124 
125  public:
133  TimedVariantBasePtr getDataField(
134  const DataFieldIdentifierBasePtr& identifier,
135  const Ice::Current& c = Ice::emptyCurrent) const;
136  void getDataField_async(
137  const AMD_ObserverInterface_getDataFieldPtr& amd,
138  const DataFieldIdentifierBasePtr& identifier,
139  const Ice::Current& c) const override;
140 
141  public:
142  TimedVariantBasePtr getDatafieldByName(
143  const std::string& channelName,
144  const std::string& datafieldName) const;
145  void getDatafieldByName_async(
146  const AMD_ObserverInterface_getDatafieldByNamePtr& amd,
147  const std::string& channelName,
148  const std::string& datafieldName,
149  const Ice::Current&) const override;
150 
151  public:
152  DatafieldRefBasePtr getDataFieldRef(
153  const DataFieldIdentifierBasePtr& identifier) const;
154  void getDataFieldRef_async(
155  const AMD_ObserverInterface_getDataFieldRefPtr& amd,
156  const DataFieldIdentifierBasePtr& identifier,
157  const Ice::Current&) const override;
158 
159  public:
160  DatafieldRefBasePtr getDatafieldRefByName(
161  const std::string& channelName,
162  const std::string& datafieldName) const;
163  void getDatafieldRefByName_async(
164  const AMD_ObserverInterface_getDatafieldRefByNamePtr& amd,
165  const std::string& channelName,
166  const std::string& datafieldName,
167  const Ice::Current&) const override;
168 
169  public:
177  TimedVariantBaseList getDataFields(
179  const Ice::Current& c);
180  void getDataFields_async(
181  const AMD_ObserverInterface_getDataFieldsPtr& amd,
183  const Ice::Current& c) override;
184 
185  public:
186  StringTimedVariantBaseMap getDatafieldsOfChannel(
187  const std::string& channelName) const;
188  void getDatafieldsOfChannel_async(
189  const AMD_ObserverInterface_getDatafieldsOfChannelPtr& amd,
190  const std::string& channelName,
191  const Ice::Current&) const override;
192 
193 
194 
195  public:
202  ChannelRegistryEntry getChannel(
203  const std::string& channelName) const;
204  void getChannel_async(
205  const AMD_ObserverInterface_getChannelPtr& amd,
206  const std::string& channelName,
207  const Ice::Current&) const override;
208 
209 
210  public:
217  ChannelRegistry getAvailableChannels(
218  bool includeMetaChannels);
219  void getAvailableChannels_async(
220  const AMD_ObserverInterface_getAvailableChannelsPtr& amd,
221  bool includeMetaChannels,
222  const Ice::Current&) override;
223 
224 
225  public:
232  StringConditionCheckMap getAvailableChecks();
233  void getAvailableChecks_async(
234  const AMD_ObserverInterface_getAvailableChecksPtr& amd,
235  const Ice::Current&) override;
236 
237 
238  public:
239  bool existsChannel(
240  const std::string& channelName) const;
241  void existsChannel_async(
242  const AMD_ObserverInterface_existsChannelPtr& amd,
243  const std::string& channelName,
244  const Ice::Current&) const override;
245 
246  public:
247  bool existsDataField(
248  const std::string& channelName,
249  const std::string& datafieldName) const;
250  void existsDataField_async(
251  const AMD_ObserverInterface_existsDataFieldPtr& amd,
252  const std::string& channelName,
253  const std::string& datafieldName,
254  const Ice::Current&) const override;
255 
256 
257  public:
265  DatafieldRefBasePtr createFilteredDatafield(
266  const DatafieldFilterBasePtr& filter,
267  const DatafieldRefBasePtr& datafieldRef);
268  void createFilteredDatafield_async(
269  const AMD_ObserverInterface_createFilteredDatafieldPtr& amd,
270  const DatafieldFilterBasePtr& filter,
271  const DatafieldRefBasePtr& datafieldRef,
272  const Ice::Current&) override;
273 
274  public:
275  DatafieldRefBasePtr createNamedFilteredDatafield(
276  const std::string& filterDatafieldName,
277  const DatafieldFilterBasePtr& filter,
278  const DatafieldRefBasePtr& datafieldRef);
279  void createNamedFilteredDatafield_async(
280  const AMD_ObserverInterface_createNamedFilteredDatafieldPtr& amd,
281  const std::string& filterDatafieldName,
282  const DatafieldFilterBasePtr& filter,
283  const DatafieldRefBasePtr& datafieldRef,
284  const Ice::Current&) override;
285 
286  public:
292  void removeFilteredDatafield(
293  const DatafieldRefBasePtr& datafieldRef);
294  void removeFilteredDatafield_async(
295  const AMD_ObserverInterface_removeFilteredDatafieldPtr& amd,
296  const DatafieldRefBasePtr& datafieldRef,
297  const Ice::Current&) override;
298 
299  public:
300  ChannelHistory getChannelHistory(
301  const std::string& channelName,
302  Ice::Float timestepMs,
303  const Ice::Current& c) const;
304  void getChannelHistory_async(
305  const AMD_ObserverInterface_getChannelHistoryPtr& amd,
306  const std::string& channelName,
307  Ice::Float timestepMs,
308  const Ice::Current& c) const override;
309 
310  public:
311  ChannelHistory getPartialChannelHistory(
312  const std::string& channelName,
313  Ice::Long startTimestamp,
314  Ice::Long endTimestamp,
315  Ice::Float timestepMs,
316  const Ice::Current& c) const;
317  void getPartialChannelHistory_async(
318  const AMD_ObserverInterface_getPartialChannelHistoryPtr& amd,
319  const std::string& channelName,
320  Ice::Long startTimestamp,
321  Ice::Long endTimestamp,
322  Ice::Float timestepMs,
323  const Ice::Current& c) const override;
324 
325  public:
326  TimedVariantBaseList getDatafieldHistory(
327  const std::string& channelName,
328  const std::string& datafieldName,
329  Ice::Float timestepMs,
330  const Ice::Current& c) const;
331  void getDatafieldHistory_async(
332  const AMD_ObserverInterface_getDatafieldHistoryPtr& amd,
333  const std::string& channelName,
334  const std::string& datafieldName,
335  Ice::Float timestepMs,
336  const Ice::Current& c) const override;
337 
338  public:
339  TimedVariantBaseList getPartialDatafieldHistory(
340  const std::string& channelName,
341  const std::string& datafieldName,
342  Ice::Long startTimestamp,
343  Ice::Long endTimestamp,
344  Ice::Float timestepMs,
345  const Ice::Current& c) const;
346  void getPartialDatafieldHistory_async(
347  const AMD_ObserverInterface_getPartialDatafieldHistoryPtr& amd,
348  const std::string& channelName,
349  const std::string& datafieldName,
350  Ice::Long startTimestamp,
351  Ice::Long endTimestamp,
352  Ice::Float timestepMs,
353  const Ice::Current& c) const override;
354 
355  // ////////////////////////////////////////////////////////////////// //
356  //internal functions
357  protected:
367  void offerChannel(std::string channelName, std::string description);
368 
379  void offerDataFieldWithDefault(std::string channelName, std::string datafieldName, const Variant& defaultValue, std::string description);
380 
391  void offerDataField(std::string channelName, std::string datafieldName, VariantTypeId type, std::string description);
392  bool offerOrUpdateDataField(std::string channelName, std::string datafieldName, const Variant& value, const std::string& description);
393 
394  void offerOrUpdateDataFieldsFlatCopy(const std::string& channelName, const StringVariantBaseMap& valueMap);
395 
403  void offerConditionCheck(std::string checkName, ConditionCheck* conditionCheck);
404 
415  void setDataField(const std::string& channelName, const std::string& datafieldName, const Variant& value, bool triggerFilterUpdate = true);
416  void setDataFieldFlatCopy(const std::string& channelName, const std::string& datafieldName, const VariantPtr& value, bool triggerFilterUpdate = true);
417  void setDataFieldsFlatCopy(const std::string& channelName, const StringVariantBaseMap& datafieldValues, bool triggerFilterUpdate = true);
418  void setDataFieldsFlatCopy(const std::string& channelName, const std::unordered_map< ::std::string, ::armarx::VariantBasePtr>& datafieldValues, bool triggerFilterUpdate = true);
419  void updateDatafieldTimestamps(const std::string& channelName, const std::unordered_map<std::string, Ice::Long>& datafieldValues);
420  void updateDatafieldTimestamps(const std::string& channelName, Ice::Long timestamp);
421  void maybeOfferChannelAndSetDataFieldsFlatCopy(
422  const std::string& channelName,
423  const std::string& description,
424  const StringVariantBaseMap& datafieldValues,
425  bool triggerFilterUpdate = true);
426 
434  void updateChannel(const std::string& channelName, const std::set<std::string>& updatedDatafields = std::set<std::string>());
435 
441  void removeChannel(std::string channelName);
442 
443  void removeDatafield(DataFieldIdentifierBasePtr id);
444 
445  std::set<std::string> updateDatafieldFilter(const std::string& channelName, const std::string& datafieldName, const VariantBasePtr& value);
446 
447  void scheduleDatafieldFilterUpdate(const std::string& channelName, const std::string& datafieldName, const VariantBasePtr& value);
448 
449 
450 
454  virtual void onInitObserver() = 0;
455 
459  virtual void onConnectObserver() = 0;
460 
464  virtual void onExitObserver() {}
465 
466  void metaUpdateTask();
467 
468  // utility methods
469  int generateId();
470 
471  private:
472  void setDataFieldFlatCopy(const DataFieldRegistry::iterator& dataFieldIter, const VariantPtr& value);
473 
474 
475  // check handling
476  ConditionCheckPtr createCheck(const CheckConfiguration& configuration) const;
477  CheckIdentifier registerCheck(const ConditionCheckPtr& check);
478  void evaluateCheck(const ConditionCheckPtr& check, const ChannelRegistryEntry& channel) const;
479 
480  // inherited from Component
481  std::string getDefaultName() const override
482  {
483  return "Observer";
484  }
485 
486  PropertyDefinitionsPtr createPropertyDefinitions() override;
487 
488  void onInitComponent() override;
489  void postOnConnectComponent() override;
490  void onConnectComponent() override;
491  void preOnDisconnectComponent() override;
492  void onExitComponent() override;
493 
494  void updateRefreshRateChannel(const std::string& channelName);
495 
496  void channelUpdateFunction();
497  void doChannelUpdate(const std::string& channelName, const std::set<std::string>& updatedDatafields);
498 
499  void updateFilters();
500 
501  void addToChannelHistory(const std::pair<IceUtil::Time, ChannelRegistryEntry>& historyEntry, const std::string& channelName);
502 
503  protected:
504  void addWorkerJob(const std::string& name, std::function<void(void)>&& f) const;
505  void addWorkerJob(const std::string& name, std::function<void(void)>&& f);
506  void callAndPassExceptionToAMD(auto& amd, auto f) const
507  {
508  try
509  {
510  f();
511  }
512  catch (std::exception& e)
513  {
515  amd->ice_exception(e);
516  }
517  catch (...)
518  {
519  auto s = GetHandledExceptionString();
520  ARMARX_ERROR << s;
521  amd->ice_exception(std::runtime_error{std::move(s)});
522  }
523  }
524  private:
525  template<class...Params>
526  void internalAddWorkerJob(const std::string& name,
527  auto* derivedPtr,
528  const auto& amd,
529  auto fnc,
530  const Params& ...ps) const
531  {
532  ARMARX_CHECK_EXPRESSION(derivedPtr);
533  addWorkerJob(name, [this, derivedPtr, amd, fnc, params = std::make_tuple(ps...)]
534  {
535  callAndPassExceptionToAMD(amd, [&]
536  {
537  auto lambda = [&](auto&& ...ps2)
538  {
539  return (derivedPtr->*fnc)(std::move(ps2)...);
540  };
541  using return_t = decltype(std::apply(lambda, params));
542  if constexpr(std::is_same_v<void, return_t>)
543  {
544 
545  std::apply(lambda, params);
546  amd->ice_response();
547  }
548  else
549  {
550  amd->ice_response(std::apply(lambda, params));
551  }
552  });
553  });
554  }
555 
556  protected:
557  template<class AMDPtr, class FReturn, class FOwner, class...FParams, class...Params>
558  void addWorkerJob(const std::string& name,
559  const AMDPtr& amd,
560  FReturn(FOwner::*fnc)(FParams...) const,
561  const Params& ...ps) const
562  {
563  static_assert(std::is_base_of_v<Observer, FOwner>);
564  internalAddWorkerJob(name, dynamic_cast<const FOwner*>(this), amd, fnc, ps...);
565  }
566  template<class AMDPtr, class FReturn, class FOwner, class...FParams, class...Params>
567  void addWorkerJob(const std::string& name,
568  const AMDPtr& amd,
569  FReturn(FOwner::*fnc)(FParams...),
570  const Params& ...ps)
571  {
572  static_assert(std::is_base_of_v<Observer, FOwner>);
573  internalAddWorkerJob(name, dynamic_cast<FOwner*>(this), amd, fnc, ps...);
574  }
575 
576  virtual void preWorkerJobs();
577  virtual void postWorkerJobs();
578  using ClockT = std::chrono::high_resolution_clock;
579  using TimepointT = typename ClockT::time_point;
580  static TimepointT Now();
581  static float TimeDeltaInMs(TimepointT t0);
582 
583  void runWorker();
584 
585  // This mutex is used by derived classes ...
586  mutable std::recursive_mutex channelsMutex;
587 
588  struct Impl;
589  std::unique_ptr<Impl> impl;
590  };
591 }
592 
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:224
armarx::DataFieldIdentifierBaseList
::std::vector< ::armarx::DataFieldIdentifierBasePtr > DataFieldIdentifierBaseList
Definition: StatechartContextInterface.h:43
armarx::Observer::Impl
Definition: Observer.cpp:48
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:918
armarx::StringVariantBaseMap
std::map< std::string, VariantBasePtr > StringVariantBaseMap
Definition: ManagedIceObject.h:111
armarx::Observer
Baseclass for all ArmarX Observers.
Definition: Observer.h:80
armarx::Observer::ClockT
std::chrono::high_resolution_clock ClockT
Definition: Observer.h:578
armarx::PropertyDefinitionContainer::prefix
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
Definition: PropertyDefinitionContainer.h:333
PeriodicTask.h
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::Observer::addWorkerJob
void addWorkerJob(const std::string &name, const AMDPtr &amd, FReturn(FOwner::*fnc)(FParams...), const Params &...ps)
Definition: Observer.h:567
RunningTask.h
armarx::Observer::addWorkerJob
void addWorkerJob(const std::string &name, const AMDPtr &amd, FReturn(FOwner::*fnc)(FParams...) const, const Params &...ps) const
Definition: Observer.h:558
IceInternal::Handle< DatafieldRef >
armarx::GetHandledExceptionString
std::string GetHandledExceptionString()
Definition: Exception.cpp:147
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::Observer::TimepointT
typename ClockT::time_point TimepointT
Definition: Observer.h:579
armarx::VariantType::Long
const VariantTypeId Long
Definition: Variant.h:917
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::VariantTypeId
Ice::Int VariantTypeId
Definition: Variant.h:44
armarx::ObserverPropertyDefinitions::ObserverPropertyDefinitions
ObserverPropertyDefinitions(std::string prefix)
Definition: Observer.h:54
Component.h
armarx::Component
Baseclass for all ArmarX ManagedIceObjects requiring properties.
Definition: Component.h:95
armarx::Observer::impl
std::unique_ptr< Impl > impl
Definition: Observer.h:588
armarx::ConditionCheck
Definition: ConditionCheck.h:56
armarx::VariantType::DatafieldRef
const VariantTypeId DatafieldRef
Definition: DatafieldRef.h:169
armarx::Observer::channelsMutex
std::recursive_mutex channelsMutex
Definition: Observer.h:586
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:70
ImportExport.h
armarx::Observer::onExitObserver
virtual void onExitObserver()
Framework hook.
Definition: Observer.h:464
ConditionCheck.h
ARMARXCORE_IMPORT_EXPORT
#define ARMARXCORE_IMPORT_EXPORT
Definition: ImportExport.h:38
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:34
armarx::ObserverPropertyDefinitions
Definition: Observer.h:50
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
identifiers
const std::list< std::string > identifiers
Definition: linux_networkload.cpp:21
armarx::Observer::callAndPassExceptionToAMD
void callAndPassExceptionToAMD(auto &amd, auto f) const
Definition: Observer.h:506