Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Together #1187

Merged
merged 45 commits into from
Nov 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
fc9ee3c
add an add entity button to component inspector. Currently only enabl…
iche033 Oct 7, 2021
12fa0da
add model editor gui plugin that inserts visuals to the scene in the …
iche033 Oct 11, 2021
5364f51
write to ECM
iche033 Oct 12, 2021
cdd9e50
support adding light links
iche033 Oct 15, 2021
4e7cec8
Merge branch 'ign-gazebo6' into model_editor_add_link
iche033 Oct 20, 2021
8f7714c
notify other GUI plugins of added/removed entities via GUI events
adlarkin Oct 22, 2021
c2055ca
Merge remote-tracking branch 'origin/adlarkin/added_removed_entities_…
iche033 Oct 22, 2021
3b967a3
use const ref for constructor input params
adlarkin Oct 25, 2021
afd5b8c
guarantee 64 bit entity IDs with gazebo::Entity instead of unsigned int
adlarkin Oct 25, 2021
3031b3c
testing makr as new entity func
iche033 Oct 25, 2021
399416c
rm printouts
iche033 Oct 25, 2021
d634a4a
Merge branch 'adlarkin/added_removed_entities_event' into model_edito…
iche033 Oct 25, 2021
79518bf
register type
iche033 Oct 25, 2021
413a075
refactor render util
iche033 Oct 26, 2021
4c81d38
workaround for avoiding crash on exit
iche033 Nov 2, 2021
44f7859
refactor, comment out unused menu items
iche033 Nov 4, 2021
fbe09f1
remove commented out code, add CreateLight function
iche033 Nov 4, 2021
2f4aa41
merge
iche033 Nov 4, 2021
b7957c8
add model editor src files
iche033 Nov 4, 2021
493d155
remove more commented out code
iche033 Nov 4, 2021
9d3b499
Merge branch 'ign-gazebo6' into model_editor_add_link
Nov 8, 2021
ac5791d
Merge branch 'ign-gazebo6' into model_editor_add_link
Nov 8, 2021
26965e3
use entity instead of entity name (#1176)
nkoenig Nov 8, 2021
539295c
Add link menu updates (#1177)
nkoenig Nov 9, 2021
1c4f59c
fix adding ellipsoid
iche033 Nov 9, 2021
7ad8ad1
Merge branch 'ign-gazebo6' into model_editor_add_link
iche033 Nov 9, 2021
0ecc731
merge model_editor into component_inspector
iche033 Nov 9, 2021
ca1a11a
merge
iche033 Nov 9, 2021
5aba7b8
fixing warnings
iche033 Nov 9, 2021
cf2d651
Merge branch 'ign-gazebo6' into model_editor_add_link
iche033 Nov 9, 2021
1a6c5b6
Merge branch 'ign-gazebo6' into model_editor_add_link
Nov 9, 2021
7dc2eae
Adjust tool tips
Nov 9, 2021
abb667d
fix adding light
iche033 Nov 9, 2021
91190cc
Merge branch 'model_editor_add_link' of github.com:ignitionrobotics/i…
Nov 9, 2021
4460933
Fix codecheck
Nov 9, 2021
a5f2c5a
Fixed documentation
Nov 10, 2021
abce9b0
Merge branch 'recreate_entities' into together
Nov 10, 2021
34e1af4
Working on model creation
Nov 10, 2021
e4a5873
merged with recreate_entities
Nov 10, 2021
bc0b9e4
Fix build
Nov 10, 2021
7e2aaf6
Added debug statements
Nov 10, 2021
c312514
use each no cache
iche033 Nov 11, 2021
e312919
fix removing component from view
iche033 Nov 11, 2021
199dafe
Fix physics
Nov 11, 2021
10b85e1
Fix codecheck
Nov 11, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/ignition/gazebo/detail/View.hh
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ template<typename ...ComponentTypeTs>
bool View<ComponentTypeTs...>::NotifyComponentRemoval(const Entity _entity,
const ComponentTypeId _typeId)
{
// if entity is still marked as to add, remove from the view
if (this->RequiresComponent(_typeId))
this->toAddEntities.erase(_entity);

// make sure that _typeId is a type required by the view and that _entity is
// already a part of the view
if (!this->RequiresComponent(_typeId) ||
Expand Down
20 changes: 18 additions & 2 deletions src/EntityComponentManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -421,11 +421,19 @@ Entity EntityComponentManager::CloneImpl(Entity _entity, Entity _parent,
}
else if (!_name.empty() && !_allowRename)
{
// if there is an entity with the same name and user indicated renaming is
// Get the entity's original parent. This is used to make sure we get
// the correct entity. For example, two different models may have a
// child with the name "link".
auto origParentComp =
this->Component<components::ParentEntity>(_entity);

// If there is an entity with the same name and user indicated renaming is
// not allowed then return null entity.
// If the entity or one of its ancestor has a Recreate component then carry
// on since the ECM is supposed to create a new entity with the same name.
Entity ent = this->EntityByComponents(components::Name(_name));
Entity ent = this->EntityByComponents(components::Name(_name),
components::ParentEntity(origParentComp->Data()));

bool hasRecreateComp = false;
Entity recreateEnt = ent;
while (recreateEnt != kNullEntity && !hasRecreateComp)
Expand Down Expand Up @@ -1061,6 +1069,14 @@ bool EntityComponentManager::CreateComponentImplementation(

this->dataPtr->createdCompTypes.insert(_componentTypeId);

// If the component is a components::ParentEntity, then make sure to
// update the entities graph.
if (_componentTypeId == components::ParentEntity::typeId)
{
auto parentComp = this->Component<components::ParentEntity>(_entity);
this->SetParentEntity(_entity, parentComp->Data());
}

return updateData;
}

Expand Down
57 changes: 43 additions & 14 deletions src/SimulationRunner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,10 @@ void SimulationRunner::Step(const UpdateInfo &_info)
IGN_PROFILE("SimulationRunner::Step");
this->currentInfo = _info;

// Process new ECM state information, typically sent from the GUI after
// a change was made to the GUI's ECM.
this->ProcessNewWorldControlState();

// Publish info
this->PublishStats();

Expand All @@ -842,10 +846,6 @@ void SimulationRunner::Step(const UpdateInfo &_info)
// Update all the systems.
this->UpdateSystems();

// Recreate any entities that have the Recreate component
// The entities will have different Entity ids but keep the same name
this->ProcessRecreateEntitiesCreate();

if (!this->Paused() &&
this->requestedRunToSimTime >
std::chrono::steady_clock::duration::zero() &&
Expand Down Expand Up @@ -873,6 +873,12 @@ void SimulationRunner::Step(const UpdateInfo &_info)
// Clear all new entities
this->entityCompMgr.ClearNewlyCreatedEntities();

// Recreate any entities that have the Recreate component
// The entities will have different Entity ids but keep the same name
// Make sure this happens after ClearNewlyCreatedEntities, otherwise the
// cloned entities will loose their "New" state.
this->ProcessRecreateEntitiesCreate();

// Process entity removals.
this->entityCompMgr.ProcessRemoveEntityRequests();

Expand Down Expand Up @@ -1148,11 +1154,13 @@ bool SimulationRunner::OnWorldControlState(const msgs::WorldControlState &_req,
{
std::lock_guard<std::mutex> lock(this->msgBufferMutex);

// update the server ECM if the request contains SerializedState information
// Copy the state information if it exists
if (_req.has_state())
this->entityCompMgr.SetState(_req.state());
// TODO(anyone) notify server systems of changes made to the ECM, if there
// were any?
{
if (this->newWorldControlState == nullptr)
this->newWorldControlState = _req.New();
this->newWorldControlState->CopyFrom(_req);
}

WorldControl control;
control.pause = _req.world_control().pause();
Expand Down Expand Up @@ -1182,7 +1190,7 @@ bool SimulationRunner::OnWorldControlState(const msgs::WorldControlState &_req,
{
control.runToSimTime = std::chrono::seconds(
_req.world_control().run_to_sim_time().sec()) +
std::chrono::nanoseconds(_req.world_control().run_to_sim_time().nsec());
std::chrono::nanoseconds(_req.world_control().run_to_sim_time().nsec());
}

this->worldControls.push_back(control);
Expand All @@ -1191,6 +1199,22 @@ bool SimulationRunner::OnWorldControlState(const msgs::WorldControlState &_req,
return true;
}

/////////////////////////////////////////////////
void SimulationRunner::ProcessNewWorldControlState()
{
std::lock_guard<std::mutex> lock(this->msgBufferMutex);
// update the server ECM if the request contains SerializedState information
if (this->newWorldControlState && this->newWorldControlState->has_state())
{
this->entityCompMgr.SetState(this->newWorldControlState->state());

delete this->newWorldControlState;
this->newWorldControlState = nullptr;
}
// TODO(anyone) notify server systems of changes made to the ECM, if there
// were any?
}

/////////////////////////////////////////////////
bool SimulationRunner::OnPlaybackControl(const msgs::LogPlaybackControl &_req,
msgs::Boolean &_res)
Expand Down Expand Up @@ -1288,7 +1312,7 @@ void SimulationRunner::ProcessRecreateEntitiesCreate()
IGN_PROFILE("SimulationRunner::ProcessRecreateEntitiesCreate");

// clone the original entities
std::set<Entity> clonedEntities;
std::set<Entity> entitiesToRemoveRecreateComp;
for (auto & ent : this->entitiesToRecreate)
{
auto nameComp = this->entityCompMgr.Component<components::Name>(ent);
Expand All @@ -1297,14 +1321,19 @@ void SimulationRunner::ProcessRecreateEntitiesCreate()
// set allowRenaming to false so the entities keep their original name
Entity clonedEntity = this->entityCompMgr.Clone(ent,
parentComp->Data(), nameComp->Data(), false);
clonedEntities.insert(clonedEntity);

entitiesToRemoveRecreateComp.insert(clonedEntity);
entitiesToRemoveRecreateComp.insert(ent);
}

// remove the Recreate component so they do not get recreated again in the
// next iteration
for (auto &ent : clonedEntities)
for (auto &ent : entitiesToRemoveRecreateComp)
{
this->entityCompMgr.RemoveComponent<components::Recreate>(ent);
if (!this->entityCompMgr.RemoveComponent<components::Recreate>(ent))
{
ignerr << "Failed to remove Recreate component from entity["
<< ent << "]" << std::endl;
}
}

this->entitiesToRecreate.clear();
Expand Down
8 changes: 8 additions & 0 deletions src/SimulationRunner.hh
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,10 @@ namespace ignition
/// Reccreate the entities by cloning from the original ones.
private: void ProcessRecreateEntitiesCreate();

/// \brief Process the new world state message, if it is present.
/// See the newWorldControlState variable below.
private: void ProcessNewWorldControlState();

/// \brief This is used to indicate that a stop event has been received.
private: std::atomic<bool> stopReceived{false};

Expand Down Expand Up @@ -639,6 +643,10 @@ namespace ignition
/// \brief A set of entities that need to be recreated
private: std::set<Entity> entitiesToRecreate;

/// \brief Holds new world state information so that it can processed
/// at the appropriate time.
private: msgs::WorldControlState *newWorldControlState{nullptr};

friend class LevelManager;
};
}
Expand Down
4 changes: 4 additions & 0 deletions src/gui/plugins/component_inspector/ModelEditor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "ignition/gazebo/components/Model.hh"
#include "ignition/gazebo/components/Name.hh"
#include "ignition/gazebo/components/ParentEntity.hh"
#include "ignition/gazebo/components/Recreate.hh"
#include "ignition/gazebo/EntityComponentManager.hh"
#include "ignition/gazebo/SdfEntityCreator.hh"

Expand Down Expand Up @@ -181,6 +182,9 @@ void ModelEditor::Update(const UpdateInfo &,
linkSdf.SetName(linkName);
auto entity = this->dataPtr->entityCreator->CreateEntities(&linkSdf);
this->dataPtr->entityCreator->SetParent(entity, eta.parentEntity);
// Make sure to mark the parent as needing recreation. This will
// tell the server to rebuild the model with the new link.
_ecm.CreateComponent(eta.parentEntity, components::Recreate());

// traverse the tree and add all new entities created by the entity
// creator to the set
Expand Down
61 changes: 55 additions & 6 deletions src/systems/physics/Physics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <iostream>
#include <deque>
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
Expand Down Expand Up @@ -122,6 +123,7 @@
#include "ignition/gazebo/components/PhysicsEnginePlugin.hh"
#include "ignition/gazebo/components/Pose.hh"
#include "ignition/gazebo/components/PoseCmd.hh"
#include "ignition/gazebo/components/Recreate.hh"
#include "ignition/gazebo/components/SelfCollide.hh"
#include "ignition/gazebo/components/SlipComplianceCmd.hh"
#include "ignition/gazebo/components/Static.hh"
Expand Down Expand Up @@ -612,6 +614,13 @@ class ignition::gazebo::systems::PhysicsPrivate
/// \brief A map between collision entity ids in the ECM to FreeGroup Entities
/// in ign-physics.
public: EntityFreeGroupMap entityFreeGroupMap;

/// \brief Set of links that were added to an existing model. This set
/// is used to track links that were added to an existing model, such as
/// through the GUI model editor, so that we can avoid premature creation
/// of links and collision elements. This also lets us suppress some
/// invalid error messages.
public: std::set<Entity> linkAddedToModel;
};

//////////////////////////////////////////////////
Expand Down Expand Up @@ -778,6 +787,9 @@ void Physics::Update(const UpdateInfo &_info, EntityComponentManager &_ecm)
//////////////////////////////////////////////////
void PhysicsPrivate::CreatePhysicsEntities(const EntityComponentManager &_ecm)
{
// Clear the set of links that were added to a model.
this->linkAddedToModel.clear();

this->CreateWorldEntities(_ecm);
this->CreateModelEntities(_ecm);
this->CreateLinkEntities(_ecm);
Expand Down Expand Up @@ -879,6 +891,9 @@ void PhysicsPrivate::CreateModelEntities(const EntityComponentManager &_ecm)
const components::Pose *_pose,
const components::ParentEntity *_parent)->bool
{
if (_ecm.EntityHasComponentType(_entity, components::Recreate::typeId))
return true;

// Check if model already exists
if (this->entityModelMap.HasEntity(_entity))
{
Expand Down Expand Up @@ -1011,6 +1026,18 @@ void PhysicsPrivate::CreateLinkEntities(const EntityComponentManager &_ecm)
const components::Pose *_pose,
const components::ParentEntity *_parent)->bool
{
// If the parent model is scheduled for recreation, then do not
// try to create a new link. This situation can occur when a link
// is added to a model from the GUI model editor.
if (_ecm.EntityHasComponentType(_parent->Data(),
components::Recreate::typeId))
{
// Add this entity to the set of newly added links to existing
// models.
this->linkAddedToModel.insert(_entity);
return true;
}

// Check if link already exists
if (this->entityLinkMap.HasEntity(_entity))
{
Expand Down Expand Up @@ -1072,6 +1099,14 @@ void PhysicsPrivate::CreateCollisionEntities(const EntityComponentManager &_ecm)
const components::CollisionElement *_collElement,
const components::ParentEntity *_parent) -> bool
{
// Check to see if this collision's parent is a link that was
// not created because the parent model is marked for recreation.
if (this->linkAddedToModel.find(_parent->Data()) !=
this->linkAddedToModel.end())
{
return true;
}

if (this->entityCollisionMap.HasEntity(_entity))
{
ignwarn << "Collision entity [" << _entity
Expand Down Expand Up @@ -2182,14 +2217,23 @@ std::map<Entity, physics::FrameData3d> PhysicsPrivate::ChangedLinks(
_ecm.Each<components::Link>(
[&](const Entity &_entity, components::Link *) -> bool
{
if (this->staticEntities.find(_entity) != this->staticEntities.end())
if (this->staticEntities.find(_entity) != this->staticEntities.end() ||
_ecm.EntityHasComponentType(_entity, components::Recreate::typeId))
{
return true;
}

// This `once` variable is here to aid in debugging, make sure to
// remove it.
auto linkPhys = this->entityLinkMap.Get(_entity);
if (nullptr == linkPhys)
{
ignerr << "Internal error: link [" << _entity
<< "] not in entity map" << std::endl;
if (this->linkAddedToModel.find(_entity) ==
this->linkAddedToModel.end())
{
ignerr << "Internal error: link [" << _entity
<< "] not in entity map" << std::endl;
}
return true;
}

Expand Down Expand Up @@ -2339,8 +2383,12 @@ bool PhysicsPrivate::GetFrameDataRelativeToWorld(const Entity _entity,
auto entityPhys = this->entityLinkMap.Get(_entity);
if (nullptr == entityPhys)
{
ignerr << "Internal error: entity [" << _entity
<< "] not in entity map" << std::endl;
// Suppress error message if the link has just been added to the model.
if (this->linkAddedToModel.find(_entity) == this->linkAddedToModel.end())
{
ignerr << "Internal error: entity [" << _entity
<< "] not in entity map" << std::endl;
}
return false;
}

Expand Down Expand Up @@ -2437,7 +2485,8 @@ void PhysicsPrivate::UpdateSim(EntityComponentManager &_ecm,
if (parentModelPoseIt == this->modelWorldPoses.end())
{
ignerr << "Internal error: parent model [" << parentEntity
<< "] does not have a world pose available" << std::endl;
<< "] does not have a world pose available for child entity["
<< entity << "]" << std::endl;
continue;
}
const math::Pose3d &parentWorldPose = parentModelPoseIt->second;
Expand Down
9 changes: 9 additions & 0 deletions test/integration/recreate_entities.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ TEST_F(RecreateEntitiesFixture, RecreateEntities)

// recreate entities only once so set it back to false
recreateEntities = false;
return;
}
});
server.AddSystem(testSystem.systemPtr);
Expand Down Expand Up @@ -306,4 +307,12 @@ TEST_F(RecreateEntitiesFixture, RecreateEntities)
EXPECT_NE(originalsphLinkEntity, sphLinkEntity);
EXPECT_NE(originalcapLinkEntity, capLinkEntity);
EXPECT_NE(originalellipLinkEntity, ellipLinkEntity);

// Run again to make sure the recreate components are removed and no
// entities to to be recreated
server.Run(true, 1, false);

auto entities = ecm->EntitiesByComponents(components::Model(),
components::Recreate());
EXPECT_TRUE(entities.empty());
}