Skip to content

Commit 5145c14

Browse files
author
Nate Koenig
committed
Merge branch 'main' into fix_guirunner_timing
2 parents b2540f2 + fa09864 commit 5145c14

File tree

13 files changed

+451
-33
lines changed

13 files changed

+451
-33
lines changed

Changelog.md

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,56 @@
332332

333333
## Ignition Gazebo 4.x
334334

335-
### Ignition Gazebo 4.x.x (202x-xx-xx)
335+
### Ignition Gazebo 4.11.x (2021-09-23)
336+
337+
1. Support locked entities, and headless video recording using sim time.
338+
* [Pull Request 862](https://github.com/ignitionrobotics/ign-gazebo/pull/862)
339+
340+
### Ignition Gazebo 4.10.x (2021-09-15)
341+
342+
1. Fixed GUI's ComponentInspector light parameter
343+
* [Pull Request 1018](https://github.com/ignitionrobotics/ign-gazebo/pull/1018)
344+
345+
1. Fix msg in entity_creation example
346+
* [Pull Request 972](https://github.com/ignitionrobotics/ign-gazebo/pull/972)
347+
348+
1. Fix selection buffer crash on resize
349+
* [Pull Request 969](https://github.com/ignitionrobotics/ign-gazebo/pull/969)
350+
351+
1. Fix crash in the follow_actor example
352+
* [Pull Request 958](https://github.com/ignitionrobotics/ign-gazebo/pull/958)
353+
354+
1. Fix joint controller with empty joint velocity data
355+
* [Pull Request 937](https://github.com/ignitionrobotics/ign-gazebo/pull/937)
356+
357+
1. Scale mode - Part2
358+
* [Pull Request 881](https://github.com/ignitionrobotics/ign-gazebo/pull/881)
359+
360+
1. Physics system: update link poses if the canonical link pose has been updated
361+
* [Pull Request 876](https://github.com/ignitionrobotics/ign-gazebo/pull/876)
362+
363+
1. Add Particle Emitter tutorial
364+
* [Pull Request 860](https://github.com/ignitionrobotics/ign-gazebo/pull/860)
365+
366+
1. Refactor RenderUtil::Update with helper functions
367+
* [Pull Request 858](https://github.com/ignitionrobotics/ign-gazebo/pull/858)
368+
369+
1. Remove unneeded camera follow offset checks
370+
* [Pull Request 857](https://github.com/ignitionrobotics/ign-gazebo/pull/857)
371+
372+
1. Added service to set camera's follow offset
373+
* [Pull Request 855](https://github.com/ignitionrobotics/ign-gazebo/pull/855)
374+
375+
1. Using math::SpeedLimiter on the ackermann_steering controller.
376+
* [Pull Request 837](https://github.com/ignitionrobotics/ign-gazebo/pull/837)
377+
378+
1. All changes merged forward from ign-gazebo3
379+
* [Pull Request 866](https://github.com/ignitionrobotics/ign-gazebo/pull/866)
380+
* [Pull Request 916](https://github.com/ignitionrobotics/ign-gazebo/pull/916)
381+
* [Pull Request 933](https://github.com/ignitionrobotics/ign-gazebo/pull/933)
382+
* [Pull Request 946](https://github.com/ignitionrobotics/ign-gazebo/pull/946)
383+
* [Pull Request 973](https://github.com/ignitionrobotics/ign-gazebo/pull/973)
384+
* [Pull Request 1017](https://github.com/ignitionrobotics/ign-gazebo/pull/1017)
336385

337386
### Ignition Gazebo 4.9.1 (2021-05-24)
338387

include/ignition/gazebo/EntityComponentManager.hh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,35 @@ namespace ignition
125125
public: void RequestRemoveEntity(const Entity _entity,
126126
bool _recursive = true);
127127

128+
/// \brief Prevent an entity and optionally its children from
129+
/// being removed.
130+
///
131+
/// This function can be useful when seek operations during log
132+
/// playback are used in conjunciton with spawned entities. For
133+
/// example, you may want to record a video based on a log file
134+
/// using a headless simulation instance. This requires a
135+
/// camera sensor which would be spawned during log playback. If
136+
/// a seek backward in time is performed during log playback, then the
137+
/// spawned camera would be removed. Use this function to prevent the
138+
/// camera from automatic removal.
139+
///
140+
/// \param[in] _entity Entity to be pinned.
141+
/// \param[in] _recursive Whether to recursively pin all child
142+
/// entities. True by default.
143+
public: void PinEntity(const Entity _entity, bool _recursive = true);
144+
145+
/// \brief Allow an entity, and optionally its children, previously
146+
/// marked as pinned to be removed.
147+
/// \param[in] _entity Entity to be unpinned.
148+
/// \param[in] _recursive Whether to recursively unpin all child
149+
/// entities. True by default.
150+
/// \sa void PinEntity(const Entity, bool)
151+
public: void UnpinEntity(const Entity _entity, bool _recursive = true);
152+
153+
/// \brief Allow all previously pinned entities to be removed.
154+
/// \sa void PinEntity(const Entity, bool)
155+
public: void UnpinAllEntities();
156+
128157
/// \brief Request to remove all entities. This will insert the request
129158
/// into a queue. The queue is processed toward the end of a simulation
130159
/// update step.

src/EntityComponentManager.cc

Lines changed: 110 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ class ignition::gazebo::EntityComponentManagerPrivate
5353
public: void InsertEntityRecursive(Entity _entity,
5454
std::unordered_set<Entity> &_set);
5555

56+
/// \brief Recursively erase an entity and all its descendants from a given
57+
/// set.
58+
/// \param[in] _entity Entity to be erased.
59+
/// \param[in, out] _set Set to erase from.
60+
public: void EraseEntityRecursive(Entity _entity,
61+
std::unordered_set<Entity> &_set);
62+
5663
/// \brief Allots the work for multiple threads prior to running
5764
/// `AddEntityToMessage`.
5865
public: void CalculateStateThreadLoad();
@@ -221,10 +228,13 @@ class ignition::gazebo::EntityComponentManagerPrivate
221228
/// \TODO(anyone) We shouldn't be giving canonical links special treatment.
222229
/// This may happen to any component that holds an Entity, so we should figure
223230
/// out a way to generalize this for any such component.
224-
std::unordered_map<Entity, Entity> oldModelCanonicalLink;
231+
public: std::unordered_map<Entity, Entity> oldModelCanonicalLink;
225232

226233
/// \brief See above
227-
std::unordered_map<Entity, Entity> oldToClonedCanonicalLink;
234+
public: std::unordered_map<Entity, Entity> oldToClonedCanonicalLink;
235+
236+
/// \brief Set of entities that are prevented from removal.
237+
public: std::unordered_set<Entity> pinnedEntities;
228238
};
229239

230240
//////////////////////////////////////////////////
@@ -456,6 +466,17 @@ void EntityComponentManagerPrivate::InsertEntityRecursive(Entity _entity,
456466
_set.insert(_entity);
457467
}
458468

469+
/////////////////////////////////////////////////
470+
void EntityComponentManagerPrivate::EraseEntityRecursive(Entity _entity,
471+
std::unordered_set<Entity> &_set)
472+
{
473+
for (const auto &vertex : this->entities.AdjacentsFrom(_entity))
474+
{
475+
this->EraseEntityRecursive(vertex.first, _set);
476+
}
477+
_set.erase(_entity);
478+
}
479+
459480
/////////////////////////////////////////////////
460481
void EntityComponentManager::RequestRemoveEntity(Entity _entity,
461482
bool _recursive)
@@ -472,6 +493,23 @@ void EntityComponentManager::RequestRemoveEntity(Entity _entity,
472493
this->dataPtr->InsertEntityRecursive(_entity, tmpToRemoveEntities);
473494
}
474495

496+
// Remove entities from tmpToRemoveEntities that are marked as
497+
// unremovable.
498+
for (auto iter = tmpToRemoveEntities.begin();
499+
iter != tmpToRemoveEntities.end();)
500+
{
501+
if (std::find(this->dataPtr->pinnedEntities.begin(),
502+
this->dataPtr->pinnedEntities.end(), *iter) !=
503+
this->dataPtr->pinnedEntities.end())
504+
{
505+
iter = tmpToRemoveEntities.erase(iter);
506+
}
507+
else
508+
{
509+
++iter;
510+
}
511+
}
512+
475513
{
476514
std::lock_guard<std::mutex> lock(this->dataPtr->entityRemoveMutex);
477515
this->dataPtr->toRemoveEntities.insert(tmpToRemoveEntities.begin(),
@@ -490,11 +528,44 @@ void EntityComponentManager::RequestRemoveEntity(Entity _entity,
490528
/////////////////////////////////////////////////
491529
void EntityComponentManager::RequestRemoveEntities()
492530
{
531+
if (this->dataPtr->pinnedEntities.empty())
493532
{
494-
std::lock_guard<std::mutex> lock(this->dataPtr->entityRemoveMutex);
495-
this->dataPtr->removeAllEntities = true;
533+
{
534+
std::lock_guard<std::mutex> lock(this->dataPtr->entityRemoveMutex);
535+
this->dataPtr->removeAllEntities = true;
536+
}
537+
this->RebuildViews();
538+
}
539+
else
540+
{
541+
std::unordered_set<Entity> tmpToRemoveEntities;
542+
543+
// Store the to-be-removed entities in a temporary set so we can
544+
// mark each of them to be removed from views that contain them.
545+
for (const auto &vertex : this->dataPtr->entities.Vertices())
546+
{
547+
if (std::find(this->dataPtr->pinnedEntities.begin(),
548+
this->dataPtr->pinnedEntities.end(), vertex.first) ==
549+
this->dataPtr->pinnedEntities.end())
550+
{
551+
tmpToRemoveEntities.insert(vertex.first);
552+
}
553+
}
554+
555+
{
556+
std::lock_guard<std::mutex> lock(this->dataPtr->entityRemoveMutex);
557+
this->dataPtr->toRemoveEntities.insert(tmpToRemoveEntities.begin(),
558+
tmpToRemoveEntities.end());
559+
}
560+
561+
for (const auto &removedEntity : tmpToRemoveEntities)
562+
{
563+
for (auto &view : this->dataPtr->views)
564+
{
565+
view.second.first->MarkEntityToRemove(removedEntity);
566+
}
567+
}
496568
}
497-
this->RebuildViews();
498569
}
499570

500571
/////////////////////////////////////////////////
@@ -1760,3 +1831,37 @@ bool EntityComponentManagerPrivate::ComponentMarkedAsRemoved(
17601831

17611832
return false;
17621833
}
1834+
1835+
/////////////////////////////////////////////////
1836+
void EntityComponentManager::PinEntity(const Entity _entity, bool _recursive)
1837+
{
1838+
if (_recursive)
1839+
{
1840+
this->dataPtr->InsertEntityRecursive(_entity,
1841+
this->dataPtr->pinnedEntities);
1842+
}
1843+
else
1844+
{
1845+
this->dataPtr->pinnedEntities.insert(_entity);
1846+
}
1847+
}
1848+
1849+
/////////////////////////////////////////////////
1850+
void EntityComponentManager::UnpinEntity(const Entity _entity, bool _recursive)
1851+
{
1852+
if (_recursive)
1853+
{
1854+
this->dataPtr->EraseEntityRecursive(_entity,
1855+
this->dataPtr->pinnedEntities);
1856+
}
1857+
else
1858+
{
1859+
this->dataPtr->pinnedEntities.erase(_entity);
1860+
}
1861+
}
1862+
1863+
/////////////////////////////////////////////////
1864+
void EntityComponentManager::UnpinAllEntities()
1865+
{
1866+
this->dataPtr->pinnedEntities.clear();
1867+
}

src/EntityComponentManager_TEST.cc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2880,6 +2880,64 @@ TEST_P(EntityComponentManagerFixture, Deprecated)
28802880
IGN_UTILS_WARN_RESUME__DEPRECATED_DECLARATION
28812881
}
28822882

2883+
//////////////////////////////////////////////////
2884+
TEST_P(EntityComponentManagerFixture, PinnedEntity)
2885+
{
2886+
// Create some entities
2887+
auto e1 = manager.CreateEntity();
2888+
EXPECT_EQ(1u, e1);
2889+
EXPECT_TRUE(manager.HasEntity(e1));
2890+
2891+
auto e2 = manager.CreateEntity();
2892+
EXPECT_TRUE(manager.SetParentEntity(e2, e1));
2893+
EXPECT_EQ(2u, e2);
2894+
EXPECT_TRUE(manager.HasEntity(e2));
2895+
2896+
auto e3 = manager.CreateEntity();
2897+
EXPECT_EQ(3u, e3);
2898+
EXPECT_TRUE(manager.HasEntity(e3));
2899+
2900+
EXPECT_EQ(3u, manager.EntityCount());
2901+
2902+
// Mark e1 as unremovable, which should also lock its child entity e2
2903+
manager.PinEntity(e1);
2904+
2905+
// Try to remove e1, which is locked entity
2906+
manager.RequestRemoveEntity(e1);
2907+
EXPECT_EQ(3u, manager.EntityCount());
2908+
EXPECT_FALSE(manager.HasEntitiesMarkedForRemoval());
2909+
manager.ProcessEntityRemovals();
2910+
EXPECT_EQ(3u, manager.EntityCount());
2911+
2912+
// Try to remove e2, which has been locked recursively
2913+
manager.RequestRemoveEntity(e2);
2914+
EXPECT_EQ(3u, manager.EntityCount());
2915+
EXPECT_FALSE(manager.HasEntitiesMarkedForRemoval());
2916+
manager.ProcessEntityRemovals();
2917+
EXPECT_EQ(3u, manager.EntityCount());
2918+
2919+
// Try to remove all entities, which should leave just e1 and e2
2920+
manager.RequestRemoveEntities();
2921+
EXPECT_TRUE(manager.HasEntitiesMarkedForRemoval());
2922+
manager.ProcessEntityRemovals();
2923+
EXPECT_EQ(2u, manager.EntityCount());
2924+
2925+
// Unmark e2, and now it should be removable.
2926+
manager.UnpinEntity(e2);
2927+
manager.RequestRemoveEntity(e2);
2928+
EXPECT_EQ(2u, manager.EntityCount());
2929+
EXPECT_TRUE(manager.HasEntitiesMarkedForRemoval());
2930+
manager.ProcessEntityRemovals();
2931+
EXPECT_EQ(1u, manager.EntityCount());
2932+
2933+
// Unmark all entities, and now it should be removable.
2934+
manager.UnpinAllEntities();
2935+
manager.RequestRemoveEntities();
2936+
EXPECT_TRUE(manager.HasEntitiesMarkedForRemoval());
2937+
manager.ProcessEntityRemovals();
2938+
EXPECT_EQ(0u, manager.EntityCount());
2939+
}
2940+
28832941
// Run multiple times. We want to make sure that static globals don't cause
28842942
// problems.
28852943
INSTANTIATE_TEST_SUITE_P(EntityComponentManagerRepeat,

src/SdfEntityCreator.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ Entity SdfEntityCreator::CreateEntities(const sdf::Model *_model,
449449
<< canonicalLinkPair.second << "\n";
450450
}
451451
}
452-
else
452+
else if(!isStatic)
453453
{
454454
ignerr << "Could not resolve the canonical link for " << _model->Name()
455455
<< "\n";

src/SdfGenerator.cc

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -411,10 +411,13 @@ namespace sdf_generator
411411
auto poseElem = _elem->GetElement("pose");
412412

413413
// Remove all attributes of poseElem
414-
sdf::ParamPtr relativeTo = poseElem->GetAttribute("relative_to");
415-
if (nullptr != relativeTo)
414+
for (const auto *attrName : {"relative_to", "degrees", "rotation_format"})
416415
{
417-
relativeTo->Reset();
416+
sdf::ParamPtr attr = poseElem->GetAttribute(attrName);
417+
if (nullptr != attr)
418+
{
419+
attr->Reset();
420+
}
418421
}
419422
poseElem->Set(poseComp->Data());
420423

@@ -505,10 +508,13 @@ namespace sdf_generator
505508
auto poseElem = _elem->GetElement("pose");
506509

507510
// Remove all attributes of poseElem
508-
sdf::ParamPtr relativeTo = poseElem->GetAttribute("relative_to");
509-
if (nullptr != relativeTo)
511+
for (const auto *attrName : {"relative_to", "degrees", "rotation_format"})
510512
{
511-
relativeTo->Reset();
513+
sdf::ParamPtr attr = poseElem->GetAttribute(attrName);
514+
if (nullptr != attr)
515+
{
516+
attr->Reset();
517+
}
512518
}
513519
poseElem->Set(poseComp->Data());
514520
return true;

0 commit comments

Comments
 (0)