DART  6.10.1
EmbeddedAspect.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2021, The DART development contributors
3  * All rights reserved.
4  *
5  * The list of contributors can be found at:
6  * https://github.com/dartsim/dart/blob/master/LICENSE
7  *
8  * This file is provided under the following "BSD-style" License:
9  * Redistribution and use in source and binary forms, with or
10  * without modification, are permitted provided that the following
11  * conditions are met:
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef DART_COMMON_DETAIL_EMBEDDEDASPECT_HPP_
34 #define DART_COMMON_DETAIL_EMBEDDEDASPECT_HPP_
35 
36 #include "dart/common/Aspect.hpp"
38 
39 namespace dart {
40 namespace common {
41 namespace detail {
42 
43 //==============================================================================
44 template <class AspectT, typename StateT>
45 void DefaultSetEmbeddedState(AspectT* aspect, const StateT& state)
46 {
47  aspect->getComposite()->setAspectState(state);
48 }
49 
50 //==============================================================================
51 template <class AspectT, typename StateT>
52 const StateT& DefaultGetEmbeddedState(const AspectT* aspect)
53 {
54  return aspect->getComposite()->getAspectState();
55 }
56 
57 //==============================================================================
58 template <class AspectT, typename PropertiesT>
60  AspectT* aspect, const PropertiesT& properties)
61 {
62  aspect->getComposite()->setAspectProperties(properties);
63 }
64 
65 //==============================================================================
66 template <class AspectT, typename PropertiesT>
67 const PropertiesT& DefaultGetEmbeddedProperties(const AspectT* aspect)
68 {
69  return aspect->getComposite()->getAspectProperties();
70 }
71 
72 //==============================================================================
73 template <
74  class BaseT,
75  class DerivedT,
76  typename StateDataT,
77  typename StateT = common::Aspect::MakeState<StateDataT>,
78  void (*setEmbeddedState)(DerivedT*, const StateT&)
79  = &DefaultSetEmbeddedState<DerivedT, StateT>,
80  const StateT& (*getEmbeddedState)(const DerivedT*)
81  = &DefaultGetEmbeddedState<DerivedT, StateT> >
82 class EmbeddedStateAspect : public BaseT
83 {
84 public:
85  using Base = BaseT;
86  using Derived = DerivedT;
87  using State = StateT;
88  using StateData = StateDataT;
89  constexpr static void (*SetEmbeddedState)(Derived*, const State&)
90  = setEmbeddedState;
91  constexpr static const State& (*GetEmbeddedState)(const Derived*)
92  = getEmbeddedState;
93 
95  {
96  Delegate
97  };
98 
100 
101  virtual ~EmbeddedStateAspect() = default;
102 
104  template <typename T>
106  {
107  using type = typename std::
108  conditional<std::is_base_of<StateData, T>::value, StateData, T>::type;
109  };
110 
113  {
114  // Do nothing
115  }
116 
120  //
121  // Dev Note: The complex construction pattern used here allows us to satisfy
122  // three simultaneous design constraints:
123  // 1. We can identify when the user has passed in relevant State information
124  // and capture that information. The type can be of **any** class type
125  // that inherits StateData.
126  // 2. We can ignore any non-State information that the user has passed in,
127  // and move that information along to the Base class.
128  // 3. We can handle arbitrary numbers of arguments of any type to pass along
129  // to the Base class.
130  // If anyone can come up with a cleaner way of accomplishing all three of
131  // these constraints, I would gladly replace this implementation. -(MXG)
132  template <typename T, typename... RemainingArgs>
133  EmbeddedStateAspect(const T& arg1, RemainingArgs&&... remainingArgs)
135  Delegate,
136  static_cast<const typename ConvertIfState<T>::type&>(arg1),
137  std::forward<RemainingArgs>(remainingArgs)...)
138  {
139  // Do nothing
140  }
141 
142  // Documentation inherited
143  void setAspectState(const Aspect::State& state) override final
144  {
145  setState(static_cast<const State&>(state));
146  }
147 
149  void setState(const State& state)
150  {
151  if (this->hasComposite())
152  {
153  SetEmbeddedState(static_cast<Derived*>(this), state);
154  return;
155  }
156 
157  // If the correct type of Composite is not available, we store this on the
158  // heap until this Aspect is moved.
159  mTemporaryState = std::make_unique<State>(state);
160  }
161 
162  // Documentation inherited
163  const Aspect::State* getAspectState() const override final
164  {
165  return &getState();
166  }
167 
169  const State& getState() const
170  {
171  if (this->hasComposite())
172  {
173  return GetEmbeddedState(static_cast<const Derived*>(this));
174  }
175 
176  if (!mTemporaryState)
177  {
178  dterr << "[detail::EmbeddedStateAspect::getState] This Aspect is not in "
179  << "a Composite, but it also does not have a temporary State "
180  << "available. This should not happen! Please report this as a "
181  << "bug!\n";
182  assert(false);
183  }
184 
185  return *mTemporaryState;
186  }
187 
188  // Documentation inherited
189  std::unique_ptr<Aspect> cloneAspect() const override
190  {
191  return std::make_unique<Derived>(this->getState());
192  }
193 
194 protected:
197  template <typename... RemainingArgs>
199  DelegateTag, const StateData& state, RemainingArgs&&... remainingArgs)
200  : Base(std::forward<RemainingArgs>(remainingArgs)...),
201  mTemporaryState(std::make_unique<State>(state))
202  {
203  // Do nothing
204  }
205 
208  template <typename... BaseArgs>
209  EmbeddedStateAspect(DelegateTag, BaseArgs&&... args)
210  : Base(std::forward<BaseArgs>(args)...)
211  {
212  // Do nothing
213  }
214 
216  void setComposite(Composite* newComposite) override
217  {
218  assert(nullptr == this->getComposite());
219 
220  Base::setComposite(newComposite);
221  if (mTemporaryState)
222  SetEmbeddedState(static_cast<Derived*>(this), *mTemporaryState);
223 
224  mTemporaryState = nullptr;
225  }
226 
228  void loseComposite(Composite* oldComposite) override
229  {
230  mTemporaryState = std::make_unique<State>(
231  GetEmbeddedState(static_cast<const Derived*>(this)));
232  Base::loseComposite(oldComposite);
233  }
234 
239  std::unique_ptr<State> mTemporaryState;
240 };
241 
242 //==============================================================================
243 template <
244  class BaseT,
245  class DerivedT,
246  typename PropertiesDataT,
248  void (*setEmbeddedProperties)(DerivedT*, const PropertiesT&)
249  = &DefaultSetEmbeddedProperties<DerivedT, PropertiesT>,
250  const PropertiesT& (*getEmbeddedProperties)(const DerivedT*)
251  = &DefaultGetEmbeddedProperties<DerivedT, PropertiesT> >
252 class EmbeddedPropertiesAspect : public BaseT
253 {
254 protected:
256  {
257  Delegate
258  };
259 
260 public:
261  using Base = BaseT;
262  using Derived = DerivedT;
263  using Properties = PropertiesT;
264  using PropertiesData = PropertiesDataT;
265  constexpr static void (*SetEmbeddedProperties)(Derived*, const Properties&)
266  = setEmbeddedProperties;
267  constexpr static const Properties& (*GetEmbeddedProperties)(const Derived*)
268  = getEmbeddedProperties;
269 
271 
272  virtual ~EmbeddedPropertiesAspect() = default;
273 
275  template <typename T>
277  {
278  using type = typename std::conditional<
279  std::is_base_of<PropertiesData, T>::value,
281  T>::type;
282  };
283 
286  {
287  // Do nothing
288  }
289 
293  //
294  // Dev Note: The complex construction pattern used here allows us to satisfy
295  // three simultaneous design constraints:
296  // 1. We can identify when the user has passed in relevant Properties
297  // information and capture that information. The type can be of **any**
298  // class type that inherits PropertiesData.
299  // 2. We can ignore any non-Properties information that the user has passed
300  // in, and move that information along to the Base class.
301  // 3. We can handle arbitrary numbers of arguments of any type to pass along
302  // to the Base class.
303  // If anyone can come up with a cleaner way of accomplishing all three of
304  // these constraints, I would gladly replace this implementation. -(MXG)
305  template <typename T, typename... RemainingArgs>
306  EmbeddedPropertiesAspect(const T& arg1, RemainingArgs&&... remainingArgs)
308  Delegate,
309  static_cast<const typename ConvertIfProperties<T>::type&>(arg1),
310  std::forward<RemainingArgs>(remainingArgs)...)
311  {
312  // Do nothing
313  }
314 
315  // Documentation inherited
317  {
318  setProperties(static_cast<const Properties&>(properties));
319  }
320 
321  // Documentation inherited
323  {
324  if (this->hasComposite())
325  {
326  SetEmbeddedProperties(static_cast<Derived*>(this), properties);
327  return;
328  }
329 
330  // If the correct type of Composite is not available, we store this on the
331  // heap until this Aspect is moved.
332  mTemporaryProperties = std::make_unique<Properties>(properties);
333  }
334 
335  // Documentation inherited
336  const Aspect::Properties* getAspectProperties() const override final
337  {
338  return &getProperties();
339  }
340 
341  // Documentation inherited
342  const Properties& getProperties() const
343  {
344  if (this->hasComposite())
345  {
346  return GetEmbeddedProperties(static_cast<const Derived*>(this));
347  }
348 
349  if (!mTemporaryProperties)
350  {
351  dterr << "[detail::EmbeddedPropertiesAspect::getProperties] This Aspect "
352  << "is not in a Composite, but it also does not have temporary "
353  << "Properties available. This should not happen! Please report "
354  << "this as a bug!\n";
355  assert(false);
356  }
357 
358  return *mTemporaryProperties;
359  }
360 
361  std::unique_ptr<Aspect> cloneAspect() const override
362  {
363  return std::make_unique<Derived>(this->getProperties());
364  }
365 
366 protected:
369  template <typename... RemainingArgs>
371  DelegateTag,
372  const PropertiesData& properties,
373  RemainingArgs&&... remainingArgs)
374  : Base(std::forward<RemainingArgs>(remainingArgs)...),
375  mTemporaryProperties(std::make_unique<Properties>(properties))
376  {
377  // Do nothing
378  }
379 
382  template <typename... BaseArgs>
384  : Base(std::forward<BaseArgs>(args)...)
385  {
386  // Do nothing
387  }
388 
390  void setComposite(Composite* newComposite) override
391  {
392  assert(nullptr == this->getComposite());
393 
394  Base::setComposite(newComposite);
395  if (mTemporaryProperties)
396  SetEmbeddedProperties(static_cast<Derived*>(this), *mTemporaryProperties);
397 
398  // Release the temporary memory
399  mTemporaryProperties = nullptr;
400  }
401 
403  void loseComposite(Composite* oldComposite) override
404  {
405  mTemporaryProperties = std::make_unique<Properties>(
406  GetEmbeddedProperties(static_cast<Derived*>(this)));
407  Base::loseComposite(oldComposite);
408  }
409 
414  std::unique_ptr<Properties> mTemporaryProperties;
415 };
416 
417 //==============================================================================
418 //
419 // These namespace-level definitions are required to enable ODR-use of static
420 // constexpr member variables.
421 //
422 // See this StackOverflow answer: http://stackoverflow.com/a/14396189/111426
423 //
424 template <
425  class BaseT,
426  class DerivedT,
427  typename StateDataT,
428  typename StateT,
429  void (*setEmbeddedState)(DerivedT*, const StateT&),
430  const StateT& (*getEmbeddedState)(const DerivedT*)>
431 constexpr void (*EmbeddedStateAspect<
432  BaseT,
433  DerivedT,
434  StateDataT,
435  StateT,
436  setEmbeddedState,
437  getEmbeddedState>::SetEmbeddedState)(DerivedT*, const StateT&);
438 
439 //==============================================================================
440 template <
441  class BaseT,
442  class DerivedT,
443  typename StateDataT,
444  typename StateT,
445  void (*setEmbeddedState)(DerivedT*, const StateT&),
446  const StateT& (*getEmbeddedState)(const DerivedT*)>
447 constexpr const StateT& (*EmbeddedStateAspect<
448  BaseT,
449  DerivedT,
450  StateDataT,
451  StateT,
452  setEmbeddedState,
453  getEmbeddedState>::GetEmbeddedState)(const DerivedT*);
454 
455 //==============================================================================
456 template <
457  class BaseT,
458  class DerivedT,
459  typename PropertiesDataT,
460  typename PropertiesT,
461  void (*setEmbeddedProperties)(DerivedT*, const PropertiesT&),
462  const PropertiesT& (*getEmbeddedProperties)(const DerivedT*)>
463 constexpr void (*EmbeddedPropertiesAspect<
464  BaseT,
465  DerivedT,
466  PropertiesDataT,
467  PropertiesT,
468  setEmbeddedProperties,
469  getEmbeddedProperties>::SetEmbeddedProperties)(
470  DerivedT*, const PropertiesT&);
471 
472 //==============================================================================
473 template <
474  class BaseT,
475  class DerivedT,
476  typename PropertiesDataT,
477  typename PropertiesT,
478  void (*setEmbeddedProperties)(DerivedT*, const PropertiesT&),
479  const PropertiesT& (*getEmbeddedProperties)(const DerivedT*)>
480 constexpr const PropertiesT& (*EmbeddedPropertiesAspect<
481  BaseT,
482  DerivedT,
483  PropertiesDataT,
484  PropertiesT,
485  setEmbeddedProperties,
486  getEmbeddedProperties>::GetEmbeddedProperties)(
487  const DerivedT*);
488 
489 } // namespace detail
490 } // namespace common
491 } // namespace dart
492 
493 #endif // DART_COMMON_DETAIL_EMBEDDEDASPECT_HPP_
#define dterr
Output an error message.
Definition: Console.hpp:49
BodyPropPtr properties
Definition: SdfParser.cpp:80
std::string type
Definition: SdfParser.cpp:82
If your Aspect has Properties, then that Properties class should inherit this Aspect::Properties clas...
Definition: Aspect.hpp:86
If your Aspect has a State, then that State class should inherit this Aspect::State class.
Definition: Aspect.hpp:65
Composite is a base class that should be virtually inherited by any class that wants to be able to ma...
Definition: Composite.hpp:53
The MakeCloneable class is used to easily create an Cloneable (such as Node::State) which simply take...
Definition: Cloneable.hpp:84
Definition: EmbeddedAspect.hpp:253
PropertiesDataT PropertiesData
Definition: EmbeddedAspect.hpp:264
const Aspect::Properties * getAspectProperties() const override final
Definition: EmbeddedAspect.hpp:336
EmbeddedPropertiesAspect(const EmbeddedPropertiesAspect &)=delete
EmbeddedPropertiesAspect(DelegateTag, const PropertiesData &properties, RemainingArgs &&... remainingArgs)
Construct this Aspect using the PropertiesData, and pass the remaining arguments into the constructor...
Definition: EmbeddedAspect.hpp:370
std::unique_ptr< Properties > mTemporaryProperties
After this Aspect is constructed and during transitions between Composite objects,...
Definition: EmbeddedAspect.hpp:414
void setComposite(Composite *newComposite) override
Pass the temporary Properties of this Aspect into the new Composite.
Definition: EmbeddedAspect.hpp:390
BaseT Base
Definition: EmbeddedAspect.hpp:261
std::unique_ptr< Aspect > cloneAspect() const override
Definition: EmbeddedAspect.hpp:361
PropertiesT Properties
Definition: EmbeddedAspect.hpp:263
DelegateTag
Definition: EmbeddedAspect.hpp:256
const Properties & getProperties() const
Definition: EmbeddedAspect.hpp:342
DerivedT Derived
Definition: EmbeddedAspect.hpp:262
EmbeddedPropertiesAspect(const T &arg1, RemainingArgs &&... remainingArgs)
Construct this Aspect.
Definition: EmbeddedAspect.hpp:306
void setAspectProperties(const Aspect::Properties &properties) override final
Definition: EmbeddedAspect.hpp:316
EmbeddedPropertiesAspect(DelegateTag, BaseArgs &&... args)
Construct this Aspect without affecting the Properties, and pass all the arguments into the construct...
Definition: EmbeddedAspect.hpp:383
void setProperties(const Properties &properties)
Definition: EmbeddedAspect.hpp:322
void loseComposite(Composite *oldComposite) override
Save the embedded Properties of this Composite before we remove the Aspect.
Definition: EmbeddedAspect.hpp:403
EmbeddedPropertiesAspect()
Construct this Aspect without affecting the Properties.
Definition: EmbeddedAspect.hpp:285
Definition: EmbeddedAspect.hpp:83
void setState(const State &state)
Set the State of this Aspect.
Definition: EmbeddedAspect.hpp:149
void loseComposite(Composite *oldComposite) override
Save the embedded State of this Composite before we remove the Aspect.
Definition: EmbeddedAspect.hpp:228
std::unique_ptr< Aspect > cloneAspect() const override
Definition: EmbeddedAspect.hpp:189
DelegateTag
Definition: EmbeddedAspect.hpp:95
DerivedT Derived
Definition: EmbeddedAspect.hpp:86
StateDataT StateData
Definition: EmbeddedAspect.hpp:88
StateT State
Definition: EmbeddedAspect.hpp:87
void setAspectState(const Aspect::State &state) override final
Definition: EmbeddedAspect.hpp:143
const Aspect::State * getAspectState() const override final
Definition: EmbeddedAspect.hpp:163
BaseT Base
Definition: EmbeddedAspect.hpp:85
const State & getState() const
Get the State of this Aspect.
Definition: EmbeddedAspect.hpp:169
void setComposite(Composite *newComposite) override
Pass the temporary State of this Aspect into the new Composite.
Definition: EmbeddedAspect.hpp:216
EmbeddedStateAspect(const EmbeddedStateAspect &)=delete
EmbeddedStateAspect(DelegateTag, BaseArgs &&... args)
Construct this Aspect without affecting the State, and pass all the arguments into the constructor of...
Definition: EmbeddedAspect.hpp:209
EmbeddedStateAspect(DelegateTag, const StateData &state, RemainingArgs &&... remainingArgs)
Construct this Aspect using the StateData, and pass the remaining arguments into the constructor of t...
Definition: EmbeddedAspect.hpp:198
EmbeddedStateAspect(const T &arg1, RemainingArgs &&... remainingArgs)
Construct this Aspect.
Definition: EmbeddedAspect.hpp:133
EmbeddedStateAspect()
Construct this Aspect without affecting the State.
Definition: EmbeddedAspect.hpp:112
std::unique_ptr< State > mTemporaryState
After this Aspect is constructed and during transitions between Composite objects,...
Definition: EmbeddedAspect.hpp:239
void DefaultSetEmbeddedProperties(AspectT *aspect, const PropertiesT &properties)
Definition: EmbeddedAspect.hpp:59
void DefaultSetEmbeddedState(AspectT *aspect, const StateT &state)
Definition: EmbeddedAspect.hpp:45
const StateT & DefaultGetEmbeddedState(const AspectT *aspect)
Definition: EmbeddedAspect.hpp:52
const PropertiesT & DefaultGetEmbeddedProperties(const AspectT *aspect)
Definition: EmbeddedAspect.hpp:67
std::unique_ptr< T > make_unique(Args &&... args)
Definition: Memory-impl.hpp:67
Definition: BulletCollisionDetector.cpp:65
Definition: SharedLibraryManager.hpp:46
Used to identify constructor arguments that can be used as Properties.
Definition: EmbeddedAspect.hpp:277
typename std::conditional< std::is_base_of< PropertiesData, T >::value, PropertiesData, T >::type type
Definition: EmbeddedAspect.hpp:281
Used to identify constructor arguments that can be used as a State.
Definition: EmbeddedAspect.hpp:106
typename std::conditional< std::is_base_of< StateData, T >::value, StateData, T >::type type
Definition: EmbeddedAspect.hpp:108