Ignition Gazebo

API Reference

6.9.0
Factory.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 #ifndef IGNITION_GAZEBO_COMPONENTS_FACTORY_HH_
18 #define IGNITION_GAZEBO_COMPONENTS_FACTORY_HH_
19 
20 #include <cstdint>
21 #include <cstring>
22 #include <map>
23 #include <memory>
24 #include <string>
25 #include <vector>
26 
28 #include <ignition/common/Util.hh>
30 #include <ignition/gazebo/detail/ComponentStorageBase.hh>
31 #include <ignition/gazebo/config.hh>
32 #include <ignition/gazebo/Export.hh>
33 #include <ignition/gazebo/Types.hh>
34 
35 namespace ignition
36 {
37 namespace gazebo
38 {
39 // Inline bracket to help doxygen filtering.
40 inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
41 namespace components
42 {
45  {
47  public: virtual ~ComponentDescriptorBase() = default;
48 
51  public: virtual std::unique_ptr<BaseComponent> Create() const = 0;
52 
56  public: virtual std::unique_ptr<BaseComponent> Create(
57  const components::BaseComponent *_data) const = 0;
58  };
59 
62  template <typename ComponentTypeT>
65  {
67  public: std::unique_ptr<BaseComponent> Create() const override
68  {
69  return std::make_unique<ComponentTypeT>();
70  }
71 
74  const components::BaseComponent *_data) const override
75  {
76  ComponentTypeT comp(*static_cast<const ComponentTypeT *>(_data));
77  return std::make_unique<ComponentTypeT>(comp);
78  }
79  };
80 
83  {
85  public: IGN_DEPRECATED(6) StorageDescriptorBase() = default;
86 
88  public: virtual ~StorageDescriptorBase() = default;
89 
92  public: virtual std::unique_ptr<ComponentStorageBase> Create() const = 0;
93  };
94 
97  template <typename ComponentTypeT>
99  : public StorageDescriptorBase
100  {
102  public: IGN_DEPRECATED(6) StorageDescriptor() = default;
103 
108  {
109  return std::make_unique<ComponentStorage<ComponentTypeT>>();
110  }
111  };
112 
114  class Factory
115  : public ignition::common::SingletonT<Factory>
116  {
125  public: template<typename ComponentTypeT>
126  void IGN_DEPRECATED(6) Register(const std::string &_type,
127  ComponentDescriptorBase *_compDesc,
128  StorageDescriptorBase * /*_storageDesc*/)
129  {
130  this->Register<ComponentTypeT>(_type, _compDesc);
131  }
132 
139  public: template<typename ComponentTypeT>
140  void Register(const std::string &_type, ComponentDescriptorBase *_compDesc)
141  {
142  // Every time a plugin which uses a component type is loaded, it attempts
143  // to register it again, so we skip it.
144  if (ComponentTypeT::typeId != 0)
145  {
146  return;
147  }
148 
149  auto typeHash = ignition::common::hash64(_type);
150 
151  // Initialize static member variable - we need to set these
152  // static members for every shared lib that uses the component, but we
153  // only add them to the maps below once.
154  ComponentTypeT::typeId = typeHash;
155  ComponentTypeT::typeName = _type;
156 
157  // Check if component has already been registered by another library
158  auto runtimeName = typeid(ComponentTypeT).name();
159  auto runtimeNameIt = this->runtimeNamesById.find(typeHash);
160  if (runtimeNameIt != this->runtimeNamesById.end())
161  {
162  // Warn user if type was previously registered with a different name.
163  // We're leaving the ID set in case this is a false difference across
164  // libraries.
165  if (runtimeNameIt->second != runtimeName)
166  {
167  std::cerr
168  << "Registered components of different types with same name: type ["
169  << runtimeNameIt->second << "] and type [" << runtimeName
170  << "] with name [" << _type << "]. Second type will not work."
171  << std::endl;
172  }
173  return;
174  }
175 
176  // This happens at static initialization time, so we can't use common
177  // console
178  std::string debugEnv;
179  ignition::common::env("IGN_DEBUG_COMPONENT_FACTORY", debugEnv);
180  if (debugEnv == "true")
181  {
182  std::cout << "Registering [" << ComponentTypeT::typeName << "]"
183  << std::endl;
184  }
185 
186  // Keep track of all types
187  this->compsById[ComponentTypeT::typeId] = _compDesc;
188  namesById[ComponentTypeT::typeId] = ComponentTypeT::typeName;
189  runtimeNamesById[ComponentTypeT::typeId] = runtimeName;
190  }
191 
195  public: template<typename ComponentTypeT>
196  void Unregister()
197  {
198  this->Unregister(ComponentTypeT::typeId);
199 
200  ComponentTypeT::typeId = 0;
201  }
202 
209  public: void Unregister(ComponentTypeId _typeId)
210  {
211  // Not registered
212  if (_typeId == 0)
213  {
214  return;
215  }
216 
217  {
218  auto it = this->compsById.find(_typeId);
219  if (it != this->compsById.end())
220  {
221  delete it->second;
222  this->compsById.erase(it);
223  }
224  }
225 
226  {
227  auto it = namesById.find(_typeId);
228  if (it != namesById.end())
229  {
230  namesById.erase(it);
231  }
232  }
233 
234  {
235  auto it = runtimeNamesById.find(_typeId);
236  if (it != runtimeNamesById.end())
237  {
238  runtimeNamesById.erase(it);
239  }
240  }
241  }
242 
247  public: template<typename ComponentTypeT>
249  {
250  return std::unique_ptr<ComponentTypeT>(static_cast<ComponentTypeT *>(
251  this->New(ComponentTypeT::typeId).release()));
252  }
253 
259  const ComponentTypeId &_type)
260  {
261  // Create a new component if a FactoryFn has been assigned to this type.
263  auto it = this->compsById.find(_type);
264  if (it != this->compsById.end() && nullptr != it->second)
265  comp = it->second->Create();
266 
267  return comp;
268  }
269 
277  const ComponentTypeId &_type, const components::BaseComponent *_data)
278  {
280 
281  if (nullptr == _data)
282  {
283  ignerr << "Requested to create a new component instance with null "
284  << "data." << std::endl;
285  }
286  else if (_type != _data->TypeId())
287  {
288  ignerr << "The typeID of _type [" << _type << "] does not match the "
289  << "typeID of _data [" << _data->TypeId() << "]." << std::endl;
290  }
291  else
292  {
293  auto it = this->compsById.find(_type);
294  if (it != this->compsById.end() && nullptr != it->second)
295  comp = it->second->Create(_data);
296  }
297 
298  return comp;
299  }
300 
306  const ComponentTypeId & /*_typeId*/)
307  {
308  return nullptr;
309  }
310 
314  {
316 
317  // Return the list of all known component types.
318  for (const auto &comp : this->compsById)
319  types.push_back(comp.first);
320 
321  return types;
322  }
323 
326  public: bool HasType(ComponentTypeId _typeId)
327  {
328  return this->compsById.find(_typeId) != this->compsById.end();
329  }
330 
333  public: std::string Name(ComponentTypeId _typeId) const
334  {
335  if (this->namesById.find(_typeId) != this->namesById.end())
336  return namesById.at(_typeId);
337 
338  return "";
339  }
340 
355 
358 
363  };
364 
373  #define IGN_GAZEBO_REGISTER_COMPONENT(_compType, _classname) \
374  class IgnGazeboComponents##_classname \
375  { \
376  public: IgnGazeboComponents##_classname() \
377  { \
378  if (_classname::typeId != 0) \
379  return; \
380  using namespace ignition;\
381  using Desc = gazebo::components::ComponentDescriptor<_classname>; \
382  gazebo::components::Factory::Instance()->Register<_classname>(\
383  _compType, new Desc());\
384  } \
385  }; \
386  static IgnGazeboComponents##_classname\
387  IgnitionGazeboComponentsInitializer##_classname;
388 }
389 }
390 }
391 }
392 
393 #endif
std::map< ComponentTypeId, std::string > namesById
A list of IDs and their equivalent names.
Definition: Factory.hh:357
A base class for an object responsible for creating storages.
Definition: Factory.hh:82
std::vector< ComponentTypeId > TypeIds() const
Get all the registered component types by ID. return Vector of component IDs.
Definition: Factory.hh:313
T endl(T... args)
STL namespace.
bool HasType(ComponentTypeId _typeId)
Check if a component type has been registered. return True if registered.
Definition: Factory.hh:326
STL class.
std::unique_ptr< BaseComponent > Create() const override
Documentation inherited.
Definition: Factory.hh:67
A factory that generates a component based on a string type.
Definition: Factory.hh:114
STL class.
bool env(const std::string &_name, std::string &_value)
T at(T... args)
T push_back(T... args)
void Unregister(ComponentTypeId _typeId)
Unregister a component so that the factory can&#39;t create instances of the component anymore...
Definition: Factory.hh:209
void Unregister()
Unregister a component so that the factory can&#39;t create instances of the component anymore...
Definition: Factory.hh:196
std::unique_ptr< ComponentStorageBase > Create() const override
Create an instance of a storage that holds ComponentTypeT components.
Definition: Factory.hh:107
std::unique_ptr< components::BaseComponent > New(const ComponentTypeId &_type, const components::BaseComponent *_data)
Create a new instance of a component, initialized with particular data.
Definition: Factory.hh:276
constexpr uint64_t hash64(std::string_view _key)
std::map< ComponentTypeId, std::string > runtimeNamesById
Keep track of the runtime names for types and warn the user if they try to register different types w...
Definition: Factory.hh:362
uint64_t ComponentTypeId
A unique identifier for a component type. A component type must be derived from components::BaseCompo...
Definition: include/ignition/gazebo/Types.hh:90
T find(T... args)
std::unique_ptr< ComponentTypeT > New()
Create a new instance of a component.
Definition: Factory.hh:248
STL class.
STL class.
#define ignerr
#define IGN_DEPRECATED(version)
std::unique_ptr< components::BaseComponent > New(const ComponentTypeId &_type)
Create a new instance of a component.
Definition: Factory.hh:258
A base class for an object responsible for creating components.
Definition: Factory.hh:44
virtual std::unique_ptr< BaseComponent > Create(const components::BaseComponent *_data) const override
Documentation inherited.
Definition: Factory.hh:73
virtual ComponentTypeId TypeId() const =0
Returns the unique ID for the component&#39;s type. The ID is derived from the name that is manually chos...
This library is part of the Ignition Robotics project.
void Register(const std::string &_type, ComponentDescriptorBase *_compDesc)
Register a component so that the factory can create instances of the component based on an ID...
Definition: Factory.hh:140
A class for an object responsible for creating components.
Definition: Factory.hh:63
A class for an object responsible for creating storages.
Definition: Factory.hh:98
Base class for all components.
Definition: Component.hh:230
std::string Name(ComponentTypeId _typeId) const
Get a component&#39;s type name given its type ID. return Unique component name.
Definition: Factory.hh:333