DART  6.7.3
CompositeData.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2019, 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 <unordered_set>
40 #include <typeinfo>
41 #include <typeindex>
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 = typename GetAspectImpl<
80  AspectT, std::is_base_of<Aspect, AspectT>::value>::Type;
81 };
82 
83 //==============================================================================
84 template <class AspectT>
85 struct GetState
86 {
88 };
89 
90 //==============================================================================
91 template <class AspectT>
93 {
95 };
96 
97 //==============================================================================
98 using CompositeStateMap = std::map< std::type_index, std::unique_ptr<Aspect::State> >;
99 using CompositePropertiesMap = std::map< std::type_index, std::unique_ptr<Aspect::Properties> >;
100 
101 //==============================================================================
102 template <typename MapType, template <class> class GetData>
103 class CompositeData : public CloneableMap<MapType>
104 {
105 public:
106 
108  template <typename... Args>
109  CompositeData(Args&&... args)
110  : CloneableMap<MapType>(std::forward<Args>(args)...)
111  {
112  // Do nothing
113  }
114 
115  virtual ~CompositeData() = default;
116 
118  template <class AspectT, typename... Args>
119  typename GetData<AspectT>::Type& create(Args&&... args)
120  {
121  using Data = typename GetData<AspectT>::Type;
122  using AspectType = typename GetAspect<AspectT>::Type;
123  using DataType = typename GetData<Aspect>::Type;
124 
125  std::unique_ptr<DataType>& data = this->mMap[typeid(AspectType)]
126  = make_unique<Data>(std::forward<Args>(args)...);
127  return static_cast<Data&>(*data);
128  }
129 
130  template <class AspectT>
131  typename GetData<AspectT>::Type* get()
132  {
133  using Data = typename GetData<AspectT>::Type;
134  using AspectType = typename GetAspect<AspectT>::Type;
135 
136  typename MapType::iterator it = this->mMap.find(typeid(AspectType));
137  if(this->mMap.end() == it)
138  return nullptr;
139 
140  return static_cast<Data*>(it->second.get());
141  }
142 
143  template <class AspectT>
144  const typename GetData<AspectT>::Type* get() const
145  {
146  return const_cast<CompositeData<MapType, GetData>*>(this)->get<AspectT>();
147  }
148 
149  template <class AspectT, typename... Args>
150  typename GetData<AspectT>::Type& getOrCreate(Args&&... args)
151  {
152  using Data = typename GetData<AspectT>::Type;
153  using AspectType = typename GetAspect<AspectT>::Type;
154 
155  auto& it = this->mMap.insert(
156  std::make_pair<std::type_index, std::unique_ptr<Data>>(
157  typeid(AspectType), nullptr));
158 
159  const bool exists = !it.second;
160  if(!exists)
161  it.first = make_unique<Data>(std::forward<Args>(args)...);
162 
163  return static_cast<Data&>(*it.first);
164  }
165 
166  template <class AspectT>
167  bool has() const
168  {
169  return (get<AspectT>() != nullptr);
170  }
171 };
172 
173 //==============================================================================
176 
177 //==============================================================================
178 template <class CompositeType, template<class> class GetData, typename... Aspects>
180 {
181 public:
182 
183  ComposeData() = default;
184 
185  ComposeData(const CompositeType&)
186  {
187  // Do nothing
188  }
189 
190  virtual ~ComposeData() = default;
191 
192  void setFrom(const CompositeType&)
193  {
194  // Do nothing
195  }
196 
197 protected:
198 
199  void _addData(CompositeType&) const
200  {
201  // Do nothing
202  }
203 };
204 
205 //==============================================================================
206 template <class CompositeType, template<class> class GetData, class AspectT,
207  typename... Remainder>
208 struct ComposeData<CompositeType, GetData, AspectT, Remainder...> :
209  public GetData<AspectT>::Type,
210  public ComposeData<CompositeType, GetData, Remainder...>
211 {
212 public:
213 
214  enum DelegateTag { Delegate };
215 
216  using ThisClass = ComposeData<CompositeType, GetData, AspectT, Remainder...>;
217  using Base = typename GetData<AspectT>::Type;
218  using Data = typename Base::Data;
220 
221  template <typename Arg>
222  struct ConvertIfData
223  {
224  using Type = typename std::conditional<
225  std::is_base_of<typename Base::Data, Arg>::value,
226  typename Base::Data, Arg>::type;
227  };
228 
229  template <typename Arg>
230  struct ConvertIfComposite
231  {
232  using Type = typename std::conditional<
233  std::is_base_of<CompositeType, Arg>::value,
234  CompositeType, Arg>::type;
235  };
236 
237  // To get byte-aligned Eigen vectors
238  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
239 
241 
242  ComposeData() = default;
243 
244  virtual ~ComposeData() = default;
245 
246  template <typename Arg1, typename... Args>
247  ComposeData(const Arg1& arg1, const Args&... args)
248  : ComposeData(
249  Delegate,
250  static_cast<const typename ConvertIfData<Arg1>::Type&>(arg1),
251  args...)
252  {
253  // This constructor delegates
254  }
255 
257  ComposeData(const CompositeType& composite)
258  : ComposeData<CompositeType, GetData, Remainder...>(composite)
259  {
260  _setBaseFrom(composite);
261  }
262 
263  template <typename... Aspects>
265  : ComposeData(static_cast<const CompositeType&>(composite))
266  {
267  // This is a delegating constructor. If we get passed another ComposeData
268  // object, then we convert it into a composite to ensure that we grab all
269  // of its aspects.
270  }
271 
272  // Dev Note: We must not use the argument 'composite' as a temporary, or else
273  // it will get deleted when it reaches the last base constructor, preventing
274  // any higher level constructors from calling _setBaseFrom(~) on it.
275  ComposeData(CompositeType&& composite)
276  : ComposeData(static_cast<const CompositeType&>(composite))
277  {
278  // This is a delegating constructor
279  }
280 
281  operator CompositeType() const
282  {
283  CompositeType composite;
284  _addData(composite);
285 
286  return composite;
287  }
288 
289  void setFrom(const CompositeType& composite)
290  {
291  _setBaseFrom(composite);
293  }
294 
295  ComposeData& operator =(const CompositeType& composite)
296  {
297  setFrom(composite);
298  return *this;
299  }
300 
305  template <typename... Args>
306  void copy(const Args&... args)
307  {
308  _findData(args...);
309  }
310 
311 protected:
312 
313  template <typename... Args>
314  ComposeData(DelegateTag, const Args&... args)
315  : ComposeData<CompositeType, GetData, Remainder...>(args...)
316  {
317  // Pass all the arguments along to the next base class
318  }
319 
320  template <typename... Args>
321  ComposeData(DelegateTag, const Data& arg1, const Args&... args)
322  : Base(arg1),
323  ComposeData<CompositeType, GetData, Remainder...>(args...)
324  {
325  // Peel off the first argument and then pass along the rest
326  }
327 
328  void _setBaseFrom(const CompositeType& composite)
329  {
330  const Base* data = composite.template get<AspectType>();
331  if(data)
332  static_cast<Base&>(*this) = *data;
333  }
334 
335  void _addData(CompositeType& composite) const
336  {
337  composite.template create<AspectType>(static_cast<const Base&>(*this));
339  }
340 
341  void _findData()
342  {
343  // Do nothing
344  }
345 
346  template <typename Arg1, typename... Args>
347  void _findData(const Arg1& arg1, const Args&... args)
348  {
349  _attemptToUse(static_cast<const typename ConvertIfData<Arg1>::Type&>(arg1));
350  _findData(args...);
351  }
352 
353  template <typename Arg>
354  void _attemptToUse(const Arg&)
355  {
356  // Do nothing
357  }
358 
359  void _attemptToUse(const typename Base::Data& data)
360  {
361  static_cast<Base&>(*this) = data;
362  }
363 
364  void _attemptToUse(const CompositeType& composite)
365  {
366  _setBaseFrom(composite);
367  }
368 };
369 
370 //==============================================================================
371 template <typename... Aspects>
373 
374 template <typename... Data>
377 
378 } // namespace detail
379 } // namespace common
380 } // namespace dart
381 
382 #endif // DART_COMMON_DETAIL_COMPOSITEDATA_HPP_
#define DART_DEFINE_ALIGNED_SHARED_OBJECT_CREATOR(class_name)
Definition: Memory.hpp:148
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:224
MapType mMap
A map containing the collection of States for the Aspect.
Definition: Cloneable.hpp:285
Definition: CompositeData.hpp:180
ComposeData(const CompositeType &)
Definition: CompositeData.hpp:185
void _addData(CompositeType &) const
Definition: CompositeData.hpp:199
void setFrom(const CompositeType &)
Definition: CompositeData.hpp:192
Definition: CompositeData.hpp:104
bool has() const
Definition: CompositeData.hpp:167
GetData< AspectT >::Type & getOrCreate(Args &&... args)
Definition: CompositeData.hpp:150
GetData< AspectT >::Type & create(Args &&... args)
Create (or replace) a piece of data in this.
Definition: CompositeData.hpp:119
GetData< AspectT >::Type * get()
Definition: CompositeData.hpp:131
CompositeData(Args &&... args)
Forwarding constructor.
Definition: CompositeData.hpp:109
const GetData< AspectT >::Type * get() const
Definition: CompositeData.hpp:144
CompositeData< CompositeStateMap, GetState > CompositeState
Definition: CompositeData.hpp:174
std::map< std::type_index, std::unique_ptr< Aspect::Properties > > CompositePropertiesMap
Definition: CompositeData.hpp:99
std::map< std::type_index, std::unique_ptr< Aspect::State > > CompositeStateMap
Definition: CompositeData.hpp:98
CompositeData< CompositePropertiesMap, GetProperties > CompositeProperties
Definition: CompositeData.hpp:175
std::multimap< dart::dynamics::Shape *, SimpleFrameShapeDnD * >::iterator iterator
Definition: Viewer.cpp:622
Definition: BulletCollisionDetector.cpp:63
Definition: SharedLibraryManager.hpp:43
typename std::conditional< std::is_base_of< CompositeType, Arg >::value, CompositeType, Arg >::type Type
Definition: CompositeData.hpp:234
typename std::conditional< std::is_base_of< typename Base::Data, Arg >::value, typename Base::Data, Arg >::type Type
Definition: CompositeData.hpp:226
void _addData(CompositeType &composite) const
Definition: CompositeData.hpp:335
typename GetData< AspectT >::Type Base
Definition: CompositeData.hpp:217
void _setBaseFrom(const CompositeType &composite)
Definition: CompositeData.hpp:328
ComposeData(DelegateTag, const Args &... args)
Definition: CompositeData.hpp:314
void copy(const Args &... args)
Grab any relevant data and copy it into this composite.
Definition: CompositeData.hpp:306
void _attemptToUse(const CompositeType &composite)
Definition: CompositeData.hpp:364
void _findData(const Arg1 &arg1, const Args &... args)
Definition: CompositeData.hpp:347
void setFrom(const CompositeType &composite)
Definition: CompositeData.hpp:289
ComposeData(DelegateTag, const Data &arg1, const Args &... args)
Definition: CompositeData.hpp:321
void _attemptToUse(const typename Base::Data &data)
Definition: CompositeData.hpp:359
ComposeData(const ComposeData< CompositeType, GetData, Aspects... > &composite)
Definition: CompositeData.hpp:264
ComposeData(CompositeType &&composite)
Definition: CompositeData.hpp:275
typename GetAspect< AspectT >::Type AspectType
Definition: CompositeData.hpp:219
ComposeData(const CompositeType &composite)
Grab relevant data out of a composite object.
Definition: CompositeData.hpp:257
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:80
Definition: CompositeData.hpp:93
typename GetAspect< AspectT >::Type::Properties Type
Definition: CompositeData.hpp:94
Definition: CompositeData.hpp:86
typename GetAspect< AspectT >::Type::State Type
Definition: CompositeData.hpp:87