DART  6.10.1
CompositeData.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_COMPOSITEDATA_HPP_
34 #define DART_COMMON_DETAIL_COMPOSITEDATA_HPP_
35 
36 #include <Eigen/Core>
37 
38 #include <map>
39 #include <typeindex>
40 #include <typeinfo>
41 #include <unordered_set>
42 
43 #include "dart/common/Aspect.hpp"
44 
45 namespace dart {
46 namespace common {
47 namespace detail {
48 
49 //==============================================================================
50 // This default template definition will be called when AspectOrComposite is
51 // an Aspect.
52 template <class AspectOrComposite, bool isAspect>
54 {
55  using Type = AspectOrComposite;
56 };
57 
58 //==============================================================================
59 // This template specialization will be called when AspectOrComposite is not
60 // an Aspect (and is presumably a composite that defines a nested Aspect type).
61 template <class AspectOrComposite>
62 struct GetAspectImpl<AspectOrComposite, false>
63 {
64  // If you get a compiler error that leads you here, then you are trying to
65  // ask for the Aspect of an object that is not associated with any Aspect.
66  // That means it does not define a nested Aspect type (such as how
67  // RevoluteJoint defines the RevoluteJoint::Aspect).
68  //
69  // Whatever function is leading to the error must be given a template type
70  // that either defines a nested type with the name Aspect, or else inherits
71  // from the type dart::common::Aspect.
72  using Type = typename AspectOrComposite::Aspect;
73 };
74 
75 //==============================================================================
76 template <class AspectT>
77 struct GetAspect
78 {
79  using Type =
81  Type;
82 };
83 
84 //==============================================================================
85 template <class AspectT>
86 struct GetState
87 {
89 };
90 
91 //==============================================================================
92 template <class AspectT>
94 {
96 };
97 
98 //==============================================================================
100  = std::map<std::type_index, std::unique_ptr<Aspect::State>>;
102  = std::map<std::type_index, std::unique_ptr<Aspect::Properties>>;
103 
104 //==============================================================================
105 template <typename MapType, template <class> class GetData>
106 class CompositeData : public CloneableMap<MapType>
107 {
108 public:
110  template <typename... Args>
111  CompositeData(Args&&... args)
112  : CloneableMap<MapType>(std::forward<Args>(args)...)
113  {
114  // Do nothing
115  }
116 
117  virtual ~CompositeData() = default;
118 
120  template <class AspectT, typename... Args>
121  typename GetData<AspectT>::Type& create(Args&&... args)
122  {
123  using Data = typename GetData<AspectT>::Type;
124  using AspectType = typename GetAspect<AspectT>::Type;
125  using DataType = typename GetData<Aspect>::Type;
126 
127  std::unique_ptr<DataType>& data = this->mMap[typeid(AspectType)]
128  = std::make_unique<Data>(std::forward<Args>(args)...);
129  return static_cast<Data&>(*data);
130  }
131 
132  template <class AspectT>
133  typename GetData<AspectT>::Type* get()
134  {
135  using Data = typename GetData<AspectT>::Type;
136  using AspectType = typename GetAspect<AspectT>::Type;
137 
138  typename MapType::iterator it = this->mMap.find(typeid(AspectType));
139  if (this->mMap.end() == it)
140  return nullptr;
141 
142  return static_cast<Data*>(it->second.get());
143  }
144 
145  template <class AspectT>
146  const typename GetData<AspectT>::Type* get() const
147  {
148  return const_cast<CompositeData<MapType, GetData>*>(this)->get<AspectT>();
149  }
150 
151  template <class AspectT, typename... Args>
152  typename GetData<AspectT>::Type& getOrCreate(Args&&... args)
153  {
154  using Data = typename GetData<AspectT>::Type;
155  using AspectType = typename GetAspect<AspectT>::Type;
156 
157  auto& it = this->mMap.insert(
158  std::make_pair<std::type_index, std::unique_ptr<Data>>(
159  typeid(AspectType), nullptr));
160 
161  const bool exists = !it.second;
162  if (!exists)
163  it.first = std::make_unique<Data>(std::forward<Args>(args)...);
164 
165  return static_cast<Data&>(*it.first);
166  }
167 
168  template <class AspectT>
169  bool has() const
170  {
171  return (get<AspectT>() != nullptr);
172  }
173 };
174 
175 //==============================================================================
179 
180 //==============================================================================
181 template <
182  class CompositeType,
183  template <class> class GetData,
184  typename... Aspects>
186 {
187 public:
188  ComposeData() = default;
189 
190  ComposeData(const CompositeType&)
191  {
192  // Do nothing
193  }
194 
195  virtual ~ComposeData() = default;
196 
197  void setFrom(const CompositeType&)
198  {
199  // Do nothing
200  }
201 
202 protected:
203  void _addData(CompositeType&) const
204  {
205  // Do nothing
206  }
207 };
208 
209 //==============================================================================
210 template <
211  class CompositeType,
212  template <class> class GetData,
213  class AspectT,
214  typename... Remainder>
215 struct ComposeData<CompositeType, GetData, AspectT, Remainder...>
216  : public GetData<AspectT>::Type,
217  public ComposeData<CompositeType, GetData, Remainder...>
218 {
219 public:
221  {
222  Delegate
223  };
224 
225  using ThisClass = ComposeData<CompositeType, GetData, AspectT, Remainder...>;
226  using Base = typename GetData<AspectT>::Type;
227  using Data = typename Base::Data;
229 
230  template <typename Arg>
231  struct ConvertIfData
232  {
233  using Type = typename std::conditional<
234  std::is_base_of<typename Base::Data, Arg>::value,
235  typename Base::Data,
236  Arg>::type;
237  };
238 
239  template <typename Arg>
240  struct ConvertIfComposite
241  {
242  using Type = typename std::conditional<
243  std::is_base_of<CompositeType, Arg>::value,
244  CompositeType,
245  Arg>::type;
246  };
247 
248  // To get byte-aligned Eigen vectors
249  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
250 
252 
253  ComposeData() = default;
254 
255  virtual ~ComposeData() = default;
256 
257  template <typename Arg1, typename... Args>
258  ComposeData(const Arg1& arg1, const Args&... args)
259  : ComposeData(
260  Delegate,
261  static_cast<const typename ConvertIfData<Arg1>::Type&>(arg1),
262  args...)
263  {
264  // This constructor delegates
265  }
266 
268  ComposeData(const CompositeType& composite)
269  : ComposeData<CompositeType, GetData, Remainder...>(composite)
270  {
271  _setBaseFrom(composite);
272  }
273 
274  template <typename... Aspects>
276  : ComposeData(static_cast<const CompositeType&>(composite))
277  {
278  // This is a delegating constructor. If we get passed another ComposeData
279  // object, then we convert it into a composite to ensure that we grab all
280  // of its aspects.
281  }
282 
283  // Dev Note: We must not use the argument 'composite' as a temporary, or else
284  // it will get deleted when it reaches the last base constructor, preventing
285  // any higher level constructors from calling _setBaseFrom(~) on it.
286  ComposeData(CompositeType&& composite)
287  : ComposeData(static_cast<const CompositeType&>(composite))
288  {
289  // This is a delegating constructor
290  }
291 
292  operator CompositeType() const
293  {
294  CompositeType composite;
295  _addData(composite);
296 
297  return composite;
298  }
299 
300  void setFrom(const CompositeType& composite)
301  {
302  _setBaseFrom(composite);
304  }
305 
306  ComposeData& operator=(const CompositeType& composite)
307  {
308  setFrom(composite);
309  return *this;
310  }
311 
316  template <typename... Args>
317  void copy(const Args&... args)
318  {
319  _findData(args...);
320  }
321 
322 protected:
323  template <typename... Args>
324  ComposeData(DelegateTag, const Args&... args)
325  : ComposeData<CompositeType, GetData, Remainder...>(args...)
326  {
327  // Pass all the arguments along to the next base class
328  }
329 
330  template <typename... Args>
331  ComposeData(DelegateTag, const Data& arg1, const Args&... args)
332  : Base(arg1), ComposeData<CompositeType, GetData, Remainder...>(args...)
333  {
334  // Peel off the first argument and then pass along the rest
335  }
336 
337  void _setBaseFrom(const CompositeType& composite)
338  {
339  const Base* data = composite.template get<AspectType>();
340  if (data)
341  static_cast<Base&>(*this) = *data;
342  }
343 
344  void _addData(CompositeType& composite) const
345  {
346  composite.template create<AspectType>(static_cast<const Base&>(*this));
348  }
349 
350  void _findData()
351  {
352  // Do nothing
353  }
354 
355  template <typename Arg1, typename... Args>
356  void _findData(const Arg1& arg1, const Args&... args)
357  {
358  _attemptToUse(static_cast<const typename ConvertIfData<Arg1>::Type&>(arg1));
359  _findData(args...);
360  }
361 
362  template <typename Arg>
363  void _attemptToUse(const Arg&)
364  {
365  // Do nothing
366  }
367 
368  void _attemptToUse(const typename Base::Data& data)
369  {
370  static_cast<Base&>(*this) = data;
371  }
372 
373  void _attemptToUse(const CompositeType& composite)
374  {
375  _setBaseFrom(composite);
376  }
377 };
378 
379 //==============================================================================
380 template <typename... Aspects>
382 
383 template <typename... Data>
386 
387 } // namespace detail
388 } // namespace common
389 } // namespace dart
390 
391 #endif // DART_COMMON_DETAIL_COMPOSITEDATA_HPP_
#define DART_DEFINE_ALIGNED_SHARED_OBJECT_CREATOR(class_name)
Definition: Memory.hpp:155
std::string type
Definition: SdfParser.cpp:82
MapHolder is a templated wrapper class that is used to allow maps of Aspect::State and Aspect::Proper...
Definition: Cloneable.hpp:221
MapType mMap
A map containing the collection of States for the Aspect.
Definition: Cloneable.hpp:280
Definition: CompositeData.hpp:186
ComposeData(const CompositeType &)
Definition: CompositeData.hpp:190
void _addData(CompositeType &) const
Definition: CompositeData.hpp:203
void setFrom(const CompositeType &)
Definition: CompositeData.hpp:197
Definition: CompositeData.hpp:107
bool has() const
Definition: CompositeData.hpp:169
GetData< AspectT >::Type & getOrCreate(Args &&... args)
Definition: CompositeData.hpp:152
GetData< AspectT >::Type & create(Args &&... args)
Create (or replace) a piece of data in this.
Definition: CompositeData.hpp:121
GetData< AspectT >::Type * get()
Definition: CompositeData.hpp:133
CompositeData(Args &&... args)
Forwarding constructor.
Definition: CompositeData.hpp:111
const GetData< AspectT >::Type * get() const
Definition: CompositeData.hpp:146
CompositeData< CompositeStateMap, GetState > CompositeState
Definition: CompositeData.hpp:176
std::map< std::type_index, std::unique_ptr< Aspect::State > > CompositeStateMap
Definition: CompositeData.hpp:100
std::map< std::type_index, std::unique_ptr< Aspect::Properties > > CompositePropertiesMap
Definition: CompositeData.hpp:102
CompositeData< CompositePropertiesMap, GetProperties > CompositeProperties
Definition: CompositeData.hpp:178
std::multimap< dart::dynamics::Shape *, SimpleFrameShapeDnD * >::iterator iterator
Definition: Viewer.cpp:620
Definition: BulletCollisionDetector.cpp:65
Definition: SharedLibraryManager.hpp:46
typename std::conditional< std::is_base_of< CompositeType, Arg >::value, CompositeType, Arg >::type Type
Definition: CompositeData.hpp:245
typename std::conditional< std::is_base_of< typename Base::Data, Arg >::value, typename Base::Data, Arg >::type Type
Definition: CompositeData.hpp:236
void _addData(CompositeType &composite) const
Definition: CompositeData.hpp:344
typename GetData< AspectT >::Type Base
Definition: CompositeData.hpp:226
void _setBaseFrom(const CompositeType &composite)
Definition: CompositeData.hpp:337
ComposeData(DelegateTag, const Args &... args)
Definition: CompositeData.hpp:324
void copy(const Args &... args)
Grab any relevant data and copy it into this composite.
Definition: CompositeData.hpp:317
void _attemptToUse(const CompositeType &composite)
Definition: CompositeData.hpp:373
void _findData(const Arg1 &arg1, const Args &... args)
Definition: CompositeData.hpp:356
void setFrom(const CompositeType &composite)
Definition: CompositeData.hpp:300
ComposeData & operator=(const CompositeType &composite)
Definition: CompositeData.hpp:306
ComposeData(DelegateTag, const Data &arg1, const Args &... args)
Definition: CompositeData.hpp:331
void _attemptToUse(const typename Base::Data &data)
Definition: CompositeData.hpp:368
ComposeData(const ComposeData< CompositeType, GetData, Aspects... > &composite)
Definition: CompositeData.hpp:275
ComposeData(CompositeType &&composite)
Definition: CompositeData.hpp:286
typename GetAspect< AspectT >::Type AspectType
Definition: CompositeData.hpp:228
ComposeData(const CompositeType &composite)
Grab relevant data out of a composite object.
Definition: CompositeData.hpp:268
typename AspectOrComposite::Aspect Type
Definition: CompositeData.hpp:72
Definition: CompositeData.hpp:54
AspectOrComposite Type
Definition: CompositeData.hpp:55
Definition: CompositeData.hpp:78
typename GetAspectImpl< AspectT, std::is_base_of< Aspect, AspectT >::value >::Type Type
Definition: CompositeData.hpp:81
Definition: CompositeData.hpp:94
typename GetAspect< AspectT >::Type::Properties Type
Definition: CompositeData.hpp:95
Definition: CompositeData.hpp:87
typename GetAspect< AspectT >::Type::State Type
Definition: CompositeData.hpp:88