-
Notifications
You must be signed in to change notification settings - Fork 289
/
Copy pathEntityComponentManager.hh
775 lines (686 loc) · 36.9 KB
/
EntityComponentManager.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
/*
* Copyright (C) 2018 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef IGNITION_GAZEBO_ENTITYCOMPONENTMANAGER_HH_
#define IGNITION_GAZEBO_ENTITYCOMPONENTMANAGER_HH_
#include <ignition/msgs/serialized.pb.h>
#include <ignition/msgs/serialized_map.pb.h>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <typeinfo>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <vector>
#include <ignition/common/Console.hh>
#include <ignition/math/graph/Graph.hh>
#include "ignition/gazebo/Entity.hh"
#include "ignition/gazebo/Export.hh"
#include "ignition/gazebo/Types.hh"
#include "ignition/gazebo/components/Component.hh"
#include "ignition/gazebo/detail/View.hh"
namespace ignition
{
namespace gazebo
{
// Inline bracket to help doxygen filtering.
inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
// Forward declarations.
class IGNITION_GAZEBO_HIDDEN EntityComponentManagerPrivate;
/// \brief Type alias for the graph that holds entities.
/// Each vertex is an entity, and the direction points from the parent to
/// its children.
/// All edges are positive booleans.
using EntityGraph = math::graph::DirectedGraph<Entity, bool>;
/** \class EntityComponentManager EntityComponentManager.hh \
* ignition/gazebo/EntityComponentManager.hh
**/
/// \brief The EntityComponentManager constructs, deletes, and returns
/// components and entities.
/// A component can be of any class which inherits from
/// `components::BaseComponent`.
class IGNITION_GAZEBO_VISIBLE EntityComponentManager
{
/// \brief Constructor
public: EntityComponentManager();
/// \brief Destructor
public: ~EntityComponentManager();
/// \brief Creates a new Entity.
/// \return An id for the Entity, or kNullEntity on failure.
public: Entity CreateEntity();
/// \brief Get the number of entities on the server.
/// \return Entity count.
public: size_t EntityCount() const;
/// \brief Request an entity deletion. This will insert the request
/// into a queue. The queue is processed toward the end of a simulation
/// update step.
///
/// \detail It is recommended that systems don't call this function
/// directly, and instead use the `gazebo::SdfEntityCreator` class to
/// remove entities.
///
/// \param[in] _entity Entity to be removed.
/// \param[in] _recursive Whether to recursively delete all child
/// entities. True by default.
public: void RequestRemoveEntity(const Entity _entity,
bool _recursive = true);
/// \brief Request to remove all entities. This will insert the request
/// into a queue. The queue is processed toward the end of a simulation
/// update step.
public: void RequestRemoveEntities();
/// \brief Get whether an Entity exists.
/// \param[in] _entity Entity to confirm.
/// \return True if the Entity exists.
public: bool HasEntity(const Entity _entity) const;
/// \brief Get the first parent of the given entity.
/// \detail Entities are not expected to have multiple parents.
/// TODO(louise) Either prevent multiple parents or provide full support
/// for multiple parents.
/// \param[in] _entity Entity.
/// \return The parent entity or kNullEntity if there's none.
public: Entity ParentEntity(const Entity _entity) const;
/// \brief Set the parent of an entity.
///
/// \detail It is recommended that systems don't call this function
/// directly, and instead use the `gazebo::SdfEntityCreator` class to
/// create entities that have the correct parent-child relationship.
///
/// \param[in] _entity Entity or kNullEntity to remove current parent.
/// \return True if successful. Will fail if entities don't exist.
public: bool SetParentEntity(const Entity _child, const Entity _parent);
/// \brief Get whether a component type has ever been created.
/// \param[in] _typeId ID of the component type to check.
/// \return True if the provided _typeId has been created.
public: bool HasComponentType(const ComponentTypeId _typeId) const;
/// \brief Check whether an entity has a specific component.
/// \param[in] _entity The entity to check.
/// \param[in] _key The component to check.
/// \return True if the component key belongs to the entity.
public: bool EntityHasComponent(const Entity _entity,
const ComponentKey &_key) const;
/// \brief Check whether an entity has a specific component type.
/// \param[in] _entity The entity to check.
/// \param[in] _typeId Component type id to check.
/// \return True if the entity exists and has at least one component
/// with the provided type.
public: bool EntityHasComponentType(const Entity _entity,
const ComponentTypeId &_typeId) const;
/// \brief Get whether an entity has all the given component types.
/// \param[in] _entity The entity to check.
/// \param[in] _types Component types to check that the Entity has.
/// \return True if the given entity has all the given types.
public: bool EntityMatches(Entity _entity,
const std::set<ComponentTypeId> &_types) const;
/// \brief Remove a component from an entity based on a key.
/// \param[in] _entity The entity.
/// \param[in] _key A key that uniquely identifies a component.
/// \return True if the entity and component existed and the component was
/// removed.
public: bool RemoveComponent(
const Entity _entity, const ComponentKey &_key);
/// \brief Remove a component from an entity based on a type id.
/// \param[in] _entity The entity.
/// \param[in] _typeId Component's type Id.
/// \return True if the entity and component existed and the component was
/// removed.
public: bool RemoveComponent(
const Entity _entity, const ComponentTypeId &_typeId);
/// \brief Remove a component from an entity based on a type.
/// \param[in] _entity The entity.
/// \tparam Component type.
/// \return True if the entity and component existed and the component was
/// removed.
public: template<typename ComponentTypeT>
bool RemoveComponent(Entity _entity);
/// \brief Rebuild all the views. This could be an expensive
/// operation.
public: void RebuildViews();
/// \brief Create a component of a particular type. This will copy the
/// _data parameter.
/// \param[in] _entity The entity that will be associated with
/// the component.
/// \param[in] _data Data used to construct the component.
/// \return Key that uniquely identifies the component.
public: template<typename ComponentTypeT>
ComponentKey CreateComponent(const Entity _entity,
const ComponentTypeT &_data);
/// \brief Get a component assigned to an entity based on a
/// component type.
/// \param[in] _entity The entity.
/// \return The component of the specified type assigned to specified
/// Entity, or nullptr if the component could not be found.
public: template<typename ComponentTypeT>
const ComponentTypeT *Component(const Entity _entity) const;
/// \brief Get a mutable component assigned to an entity based on a
/// component type.
/// \param[in] _entity The entity.
/// \return The component of the specified type assigned to specified
/// Entity, or nullptr if the component could not be found.
public: template<typename ComponentTypeT>
ComponentTypeT *Component(const Entity _entity);
/// \brief Get a component based on a key.
/// \param[in] _key A key that uniquely identifies a component.
/// \return The component associated with the key, or nullptr if the
/// component could not be found.
public: template<typename ComponentTypeT>
const ComponentTypeT *Component(const ComponentKey &_key) const;
/// \brief Get a mutable component based on a key.
/// \param[in] _key A key that uniquely identifies a component.
/// \return The component associated with the key, or nullptr if the
/// component could not be found.
public: template<typename ComponentTypeT>
ComponentTypeT *Component(const ComponentKey &_key);
/// \brief Get a mutable component assigned to an entity based on a
/// component type. If the component doesn't exist, create it and
/// initialize with the given default value.
/// \param[in] _entity The entity.
/// \param[in] _default The value that should be used to construct
/// the component in case the component doesn't exist.
/// \return The component of the specified type assigned to the specified
/// entity.
public: template<typename ComponentTypeT>
ComponentTypeT *ComponentDefault(Entity _entity,
const typename ComponentTypeT::Type &_default =
typename ComponentTypeT::Type());
/// \brief Get the data from a component.
/// * If the component type doesn't hold any data, this won't compile.
/// * If the entity doesn't have that component, it will return nullopt.
/// * If the entity has the component, return its data.
/// \param[in] _entity The entity.
/// \tparam ComponentTypeT Component type
/// \return The data of the component of the specified type assigned to
/// specified Entity, or nullptr if the component could not be found.
public: template<typename ComponentTypeT>
std::optional<typename ComponentTypeT::Type> ComponentData(
const Entity _entity) const;
/// \brief Set the data from a component.
/// * If the component type doesn't hold any data, this won't compile.
/// * If the entity doesn't have that component, the component will be
/// created.
/// * If the entity has the component, its data will be updated.
/// \param[in] _entity The entity.
/// \param[in] _data New component data
/// \tparam ComponentTypeT Component type
/// \return True if data has changed. It will always be true if the data
/// type doesn't have an equality operator.
public: template<typename ComponentTypeT>
bool SetComponentData(const Entity _entity,
const typename ComponentTypeT::Type &_data);
/// \brief Get the type IDs of all components attached to an entity.
/// \param[in] _entity Entity to check.
/// \return All the component type IDs.
public: std::unordered_set<ComponentTypeId> ComponentTypes(
Entity _entity) const;
/// \brief The first component instance of the specified type.
/// \return First component instance of the specified type, or nullptr
/// if the type does not exist.
public: template<typename ComponentTypeT>
const ComponentTypeT *First() const;
/// \brief The first component instance of the specified type.
/// \return First component instance of the specified type, or nullptr
/// if the type does not exist.
public: template<typename ComponentTypeT>
ComponentTypeT *First();
/// \brief Get an entity which matches the value of all the given
/// components. For example, the following will return the entity which
/// has an name component equal to "name" and has a model component:
///
/// auto entity = EntityByComponents(components::Name("name"),
/// components::Model());
///
/// \detail Component type must have inequality operator.
///
/// \param[in] _desiredComponents All the components which must match.
/// \return Entity or kNullEntity if no entity has the exact components.
public: template<typename ...ComponentTypeTs>
Entity EntityByComponents(
const ComponentTypeTs &..._desiredComponents) const;
/// \brief Get all entities which match the value of all the given
/// components. For example, the following will return the entities which
/// have a name component equal to "camera" and a sensor component:
///
/// auto entities = EntitiesByComponents(components::Name("camera"),
/// components::Sensor());
///
/// \detail Component type must have inequality operator.
///
/// \param[in] _desiredComponents All the components which must match.
/// \return All matching entities, or an empty vector if no child entity
/// has the exact components.
public: template<typename ...ComponentTypeTs>
std::vector<Entity> EntitiesByComponents(
const ComponentTypeTs &..._desiredComponents) const;
/// \brief Get all entities which match the value of all the given
/// components and are immediate children of a given parent entity.
/// For example, the following will return a child of entity `parent`
/// which has an int component equal to 123, and a string component
/// equal to "name":
///
/// auto entity = ChildrenByComponents(parent, 123, std::string("name"));
///
/// \detail Component type must have inequality operator.
///
/// \param[in] _parent Entity which should be an immediate parent of the
/// returned entity.
/// \param[in] _desiredComponents All the components which must match.
/// \return All matching entities, or an empty vector if no child entity
/// has the exact components.
public: template<typename ...ComponentTypeTs>
std::vector<Entity> ChildrenByComponents(Entity _parent,
const ComponentTypeTs &..._desiredComponents) const;
/// why is this required?
private: template <typename T>
struct identity; // NOLINT
/// \brief A version of Each() that doesn't use a cache. The cached
/// version, Each(), is preferred.
/// Get all entities which contain given component types, as well
/// as the components.
/// \param[in] _f Callback function to be called for each matching entity.
/// The function parameter are all the desired component types, in the
/// order they're listed on the template. The callback function can
/// return false to stop subsequent calls to the callback, otherwise
/// a true value should be returned.
/// \tparam ComponentTypeTs All the desired component types.
/// \warning This function should not be called outside of System's
/// PreUpdate, Update, or PostUpdate callbacks.
public: template<typename ...ComponentTypeTs>
void EachNoCache(typename identity<std::function<
bool(const Entity &_entity,
const ComponentTypeTs *...)>>::type _f) const;
/// \brief A version of Each() that doesn't use a cache. The cached
/// version, Each(), is preferred.
/// Get all entities which contain given component types, as well
/// as the mutable components.
/// \param[in] _f Callback function to be called for each matching entity.
/// The function parameter are all the desired component types, in the
/// order they're listed on the template. The callback function can
/// return false to stop subsequent calls to the callback, otherwise
/// a true value should be returned.
/// \tparam ComponentTypeTs All the desired mutable component types.
/// \warning This function should not be called outside of System's
/// PreUpdate, Update, or PostUpdate callbacks.
public: template<typename ...ComponentTypeTs>
void EachNoCache(typename identity<std::function<
bool(const Entity &_entity,
ComponentTypeTs *...)>>::type _f);
/// \brief Get all entities which contain given component types, as well
/// as the components. Note that an entity marked for removal (but not
/// processed yet) will be included in the list of entities iterated by
/// this call.
/// \param[in] _f Callback function to be called for each matching entity.
/// The function parameter are all the desired component types, in the
/// order they're listed on the template. The callback function can
/// return false to stop subsequent calls to the callback, otherwise
/// a true value should be returned.
/// \tparam ComponentTypeTs All the desired component types.
/// \warning This function should not be called outside of System's
/// PreUpdate, Update, or PostUpdate callbacks.
public: template<typename ...ComponentTypeTs>
void Each(typename identity<std::function<
bool(const Entity &_entity,
const ComponentTypeTs *...)>>::type _f) const;
/// \brief Get all entities which contain given component types, as well
/// as the mutable components. Note that an entity marked for removal (but
/// not processed yet) will be included in the list of entities iterated
/// by this call.
/// \param[in] _f Callback function to be called for each matching entity.
/// The function parameter are all the desired component types, in the
/// order they're listed on the template. The callback function can
/// return false to stop subsequent calls to the callback, otherwise
/// a true value should be returned.
/// \tparam ComponentTypeTs All the desired mutable component types.
/// \warning This function should not be called outside of System's
/// PreUpdate, Update, or PostUpdate callbacks.
public: template<typename ...ComponentTypeTs>
void Each(typename identity<std::function<
bool(const Entity &_entity,
ComponentTypeTs *...)>>::type _f);
/// \brief Call a function for each parameter in a pack.
/// \param[in] _f Function to be called.
/// \param[in] _components Parameters which should be passed to the
/// function.
public: template <class Function, class... ComponentTypeTs>
static void ForEach(Function _f, const ComponentTypeTs &... _components);
/// \brief Get all newly created entities which contain given component
/// types, as well as the components. This "newness" is cleared at the end
/// of a simulation step.
/// \param[in] _f Callback function to be called for each matching entity.
/// The function parameter are all the desired component types, in the
/// order they're listed on the template. The callback function can
/// return false to stop subsequent calls to the callback, otherwise
/// a true value should be returned.
/// \tparam ComponentTypeTs All the desired component types.
/// \warning This function should not be called outside of System's
/// PreUpdate, callback. The result of call after PreUpdate is invalid
public: template <typename... ComponentTypeTs>
void EachNew(typename identity<std::function<
bool(const Entity &_entity,
ComponentTypeTs *...)>>::type _f);
/// \brief Get all newly created entities which contain given component
/// types, as well as the components. This "newness" is cleared at the end
/// of a simulation step. This is the const version.
/// \param[in] _f Callback function to be called for each matching entity.
/// The function parameter are all the desired component types, in the
/// order they're listed on the template. The callback function can
/// return false to stop subsequent calls to the callback, otherwise
/// a true value should be returned.
/// \tparam ComponentTypeTs All the desired component types.
/// \warning This function should not be called outside of System's
/// PreUpdate, callback. The result of call after PreUpdate is invalid
public: template <typename... ComponentTypeTs>
void EachNew(typename identity<std::function<
bool(const Entity &_entity,
const ComponentTypeTs *...)>>::type _f) const;
/// \brief Get all entities which contain given component types and are
/// about to be removed, as well as the components.
/// \param[in] _f Callback function to be called for each matching entity.
/// The function parameter are all the desired component types, in the
/// order they're listed on the template. The callback function can
/// return false to stop subsequent calls to the callback, otherwise
/// a true value should be returned.
/// \tparam ComponentTypeTs All the desired component types.
/// \warning This function should not be called outside of System's
/// PostUpdate callback.
public: template<typename ...ComponentTypeTs>
void EachRemoved(typename identity<std::function<
bool(const Entity &_entity,
const ComponentTypeTs *...)>>::type _f) const;
/// \brief Get a graph with all the entities. Entities are vertices and
/// edges point from parent to children.
/// \return Entity graph.
public: const EntityGraph &Entities() const;
/// \brief Get all entities which are descendants of a given entity,
/// including the entity itself.
/// \param[in] _entity Entity whose descendants we want.
/// \return All child entities recursively, including _entity. It will be
/// empty if the entity doesn't exist.
public: std::unordered_set<Entity> Descendants(Entity _entity) const;
/// \brief Get a message with the serialized state of the given entities
/// and components.
/// \detail The header of the message will not be populated, it is the
/// responsibility of the caller to timestamp it before use.
/// \param[in] _entities Entities to be serialized. Leave empty to get
/// all entities.
/// \param[in] _types Type ID of components to be serialized. Leave empty
/// to get all components.
public: msgs::SerializedState State(
const std::unordered_set<Entity> &_entities = {},
const std::unordered_set<ComponentTypeId> &_types = {}) const;
/// \brief Get a message with the serialized state of all entities and
/// components that are changing in the current iteration
///
/// Currently supported:
/// * New entities and all of their components
/// * Removed entities and all of their components
///
/// Future work:
/// * Entities which had a component added
/// * Entities which had a component removed
/// * Entities which had a component modified
///
/// \detail The header of the message will not be populated, it is the
/// responsibility of the caller to timestamp it before use.
public: msgs::SerializedState ChangedState() const;
/// \brief Get whether there are new entities.
/// \return True if there are new entities.
public: bool HasNewEntities() const;
/// \brief Get whether there are any entities marked to be removed.
/// \return True if there are entities marked to be removed.
public: bool HasEntitiesMarkedForRemoval() const;
/// \brief Get whether there are one-time component changes. These changes
/// do not happen frequently and should be processed immediately.
/// \return True if there are any components with one-time changes.
public: bool HasOneTimeComponentChanges() const;
/// \brief Get the components types that are marked as periodic changes.
/// \return All the components that at least one entity marked as
/// periodic changes.
public: std::unordered_set<ComponentTypeId>
ComponentTypesWithPeriodicChanges() const;
/// \brief Set the absolute state of the ECM from a serialized message.
/// Entities / components that are in the new state but not in the old
/// one will be created.
/// Entities / components that are marked as removed will be removed, but
/// they won't be removed if they're not present in the state.
/// \detail The header of the message will not be handled, it is the
/// responsibility of the caller to use the timestamp.
/// \param[in] _stateMsg Message containing state to be set.
public: void SetState(const msgs::SerializedState &_stateMsg);
/// \brief Get a message with the serialized state of the given entities
/// and components.
/// \detail The header of the message will not be populated, it is the
/// responsibility of the caller to timestamp it before use.
/// \param[in] _entities Entities to be serialized. Leave empty to get
/// all entities.
/// \param[in] _types Type ID of components to be serialized. Leave empty
/// to get all components.
/// \param[in] _full True to get all the entities and components.
/// False will get only components and entities that have changed.
public: void State(
msgs::SerializedStateMap &_state,
const std::unordered_set<Entity> &_entities = {},
const std::unordered_set<ComponentTypeId> &_types = {},
bool _full = false) const;
/// \brief Get a message with the serialized state of all entities and
/// components that are changing in the current iteration
///
/// Currently supported:
/// * New entities and all of their components
/// * Removed entities and all of their components
///
/// Future work:
/// * Entities which had a component added
/// * Entities which had a component removed
/// * Entities which had a component modified
///
/// \param[in] _state New serialized state.
/// \detail The header of the message will not be populated, it is the
/// responsibility of the caller to timestamp it before use.
public: void ChangedState(msgs::SerializedStateMap &_state) const;
/// \brief Set the absolute state of the ECM from a serialized message.
/// Entities / components that are in the new state but not in the old
/// one will be created.
/// Entities / components that are marked as removed will be removed, but
/// they won't be removed if they're not present in the state.
/// \detail The header of the message will not be handled, it is the
/// responsibility of the caller to use the timestamp.
/// \param[in] _stateMsg Message containing state to be set.
public: void SetState(const msgs::SerializedStateMap &_stateMsg);
/// \brief Set the changed state of a component.
/// \param[in] _entity The entity.
/// \param[in] _type Type of the component.
/// \param[in] _c Changed state value, defaults to one-time-change.
public: void SetChanged(
const Entity _entity, const ComponentTypeId _type,
gazebo::ComponentState _c = ComponentState::OneTimeChange);
/// \brief Get a component's state.
/// \param[in] _entity Entity that contains the component.
/// \param[in] _typeId Component type ID.
/// \return Component's current state
public: gazebo::ComponentState ComponentState(const Entity _entity,
const ComponentTypeId _typeId) const;
/// \brief All future entities will have an id that starts at _offset.
/// This can be used to avoid entity id collisions, such as during log
/// playback.
/// \param[in] _offset Offset value.
public: void SetEntityCreateOffset(uint64_t _offset);
/// \brief Clear the list of newly added entities so that a call to
/// EachAdded after this will have no entities to iterate. This function
/// is protected to facilitate testing.
protected: void ClearNewlyCreatedEntities();
/// \brief Clear the list of removed components so that a call to
/// RemoveComponent doesn't make the list grow indefinitely.
protected: void ClearRemovedComponents();
/// \brief Process all entity remove requests. This will remove
/// entities and their components. This function is protected to
/// facilitate testing.
protected: void ProcessRemoveEntityRequests();
/// \brief Mark all components as not changed.
protected: void SetAllComponentsUnchanged();
/// \brief Get whether an Entity exists and is new.
///
/// Entities are considered new in the time between their creation and a
/// call to ClearNewlyCreatedEntities
/// \param[in] _entity Entity id to check.
/// \return True if the Entity is new.
private: bool IsNewEntity(const Entity _entity) const;
/// \brief Get whether an Entity has been marked to be removed.
/// \param[in] _entity Entity id to check.
/// \return True if the Entity has been marked to be removed.
private: bool IsMarkedForRemoval(const Entity _entity) const;
/// \brief Delete an existing Entity.
/// \param[in] _entity The entity to remove.
/// \returns True if the Entity existed and was deleted.
private: bool RemoveEntity(const Entity _entity);
/// \brief The first component instance of the specified type.
/// \return First component instance of the specified type, or nullptr
/// if the type does not exist.
private: components::BaseComponent *First(
const ComponentTypeId _componentTypeId);
/// \brief Implementation of CreateComponent.
/// \param[in] _entity The entity that will be associated with
/// the component.
/// \param[in] _componentTypeId Id of the component type.
/// \param[in] _data Data used to construct the component.
/// \return Key that uniquely identifies the component.
private: ComponentKey CreateComponentImplementation(
const Entity _entity,
const ComponentTypeId _componentTypeId,
const components::BaseComponent *_data);
/// \brief Get a component based on a component type.
/// \param[in] _entity The entity.
/// \param[in] _type Id of the component type.
/// \return The component of the specified type assigned to specified
/// Entity, or nullptr if the component could not be found.
private: const components::BaseComponent *ComponentImplementation(
const Entity _entity,
const ComponentTypeId _type) const;
/// \brief Get a mutable component based on a component type.
/// \param[in] _entity The entity.
/// \param[in] _type Id of the component type.
/// \return The component of the specified type assigned to specified
/// Entity, or nullptr if the component could not be found.
private: components::BaseComponent *ComponentImplementation(
const Entity _entity,
const ComponentTypeId _type);
/// \brief Get a component based on a key.
/// \param[in] _key A key that uniquely identifies a component.
/// \return The component associated with the key, or nullptr if the
/// component could not be found.
private: const components::BaseComponent *ComponentImplementation(
const ComponentKey &_key) const;
/// \brief Get a mutable component based on a key.
/// \param[in] _key A key that uniquely identifies a component.
/// \return The component associated with the key, or nullptr if the
/// component could not be found.
private: components::BaseComponent *ComponentImplementation(
const ComponentKey &_key);
/// \brief End of the AddComponentToView recursion. This function is
/// called when Rest is empty.
/// \param[in, out] _view The FirstComponent will be added to the
/// _view.
/// \param[in] _entity The entity.
private: template<typename FirstComponent,
typename ...RemainingComponents,
typename std::enable_if<
sizeof...(RemainingComponents) == 0, int>::type = 0>
void AddComponentsToView(detail::View &_view,
const Entity _entity) const;
/// \brief Recursively add components to a view. This function is
/// called when Rest is NOT empty.
/// \param[in, out] _view The FirstComponent will be added to the
/// _view.
/// \param[in] _entity The entity.
private: template<typename FirstComponent,
typename ...RemainingComponents,
typename std::enable_if<
sizeof...(RemainingComponents) != 0, int>::type = 0>
void AddComponentsToView(detail::View &_view,
const Entity _entity) const;
/// \brief Find a View that matches the set of ComponentTypeIds. If
/// a match is not found, then a new view is created.
/// \tparam ComponentTypeTs All the component types that define a view.
/// \return A reference to the view.
private: template<typename ...ComponentTypeTs>
detail::View &FindView() const;
/// \brief Find a view based on the provided component type ids.
/// \param[in] _types The component type ids that serve as a key into
/// a map of views.
/// \param[out] _iter Iterator to the found element in the view map.
/// Check the return value to see if this iterator is valid.
/// \return True if the view was found, false otherwise.
private: bool FindView(const std::set<ComponentTypeId> &_types,
std::map<detail::ComponentTypeKey,
detail::View>::iterator &_iter) const; // NOLINT
/// \brief Add a new view to the set of stored views.
/// \param[in] _types The set of component type ids that is the key
/// for the view.
/// \param[in] _view The view to add.
/// \return An iterator to the view.
private: std::map<detail::ComponentTypeKey, detail::View>::iterator
AddView(const std::set<ComponentTypeId> &_types,
detail::View &&_view) const;
/// \brief Update views that contain the provided entity.
/// \param[in] _entity The entity.
private: void UpdateViews(const Entity _entity);
/// \brief Get a component ID based on an entity and the component's type.
/// \param[in] _entity The entity.
/// \param[in] _type Component type ID.
private: ComponentId EntityComponentIdFromType(
const Entity _entity, const ComponentTypeId _type) const;
/// \brief Add an entity and its components to a serialized state message.
/// \param[out] _msg The state message.
/// \param[in] _entity The entity to be added.
/// \param[in] _types Component types to be added. Leave empty for all
/// components.
private: void AddEntityToMessage(msgs::SerializedState &_msg,
Entity _entity,
const std::unordered_set<ComponentTypeId> &_types = {}) const;
/// \brief Private data pointer.
private: std::unique_ptr<EntityComponentManagerPrivate> dataPtr;
/// \brief Add an entity and its components to a serialized state message.
/// \param[out] _msg The state message.
/// \param[in] _entity The entity to be added.
/// \param[in] _types Component types to be added. Leave empty for all
/// components.
/// \param[in] _full True to get all the entities and components.
/// False will get only components and entities that have changed.
/// \note This function will mark `Changed` components as not changed.
/// See the todo in the implementation.
private: void AddEntityToMessage(msgs::SerializedStateMap &_msg,
Entity _entity,
const std::unordered_set<ComponentTypeId> &_types = {},
bool _full = false) const;
// Make runners friends so that they can manage entity creation and
// removal. This should be safe since runners are internal
// to Gazebo.
friend class GuiRunner;
friend class SimulationRunner;
// Make network managers friends so they have control over component
// states. Like the runners, the managers are internal.
friend class NetworkManagerPrimary;
friend class NetworkManagerSecondary;
// Make View a friend so that it can access components.
// This should be safe since View is internal to Gazebo.
friend class detail::View;
};
}
}
}
#include "ignition/gazebo/detail/EntityComponentManager.hh"
#endif