-
Notifications
You must be signed in to change notification settings - Fork 270
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
Support recreating model entities #1170
Changes from 27 commits
c4a0516
2f3b87f
d10bfec
2e6c570
0cf71a9
18b26c2
1477a68
92bed4e
d553e8f
103cdf0
c4eb390
2029d2b
9fa9a84
2d8d50f
1a3b5ee
8d0b08d
c2898a8
5c0a4c0
39a1d34
d139bd1
d56e983
638d43d
68faa5a
2775d05
8f7fe57
370ffd2
304d004
14d78f3
cdee88d
8a6552e
f399b49
c897c41
0ab3217
0576793
9932f2a
df289fb
29a2cac
f4df9c9
ff40d98
fcfc6e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* Copyright (C) 2021 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_COMPONENTS_RECREATE_HH_ | ||
#define IGNITION_GAZEBO_COMPONENTS_RECREATE_HH_ | ||
|
||
#include <ignition/gazebo/components/Factory.hh> | ||
#include <ignition/gazebo/components/Component.hh> | ||
#include <ignition/gazebo/config.hh> | ||
|
||
namespace ignition | ||
{ | ||
namespace gazebo | ||
{ | ||
// Inline bracket to help doxygen filtering. | ||
inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { | ||
namespace components | ||
{ | ||
/// \brief A component that identifies an entity needs to be recreated | ||
using Recreate = Component<NoData, class RecreateTag>; | ||
IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.Recreate", Recreate) | ||
} | ||
} | ||
} | ||
} | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,8 +27,10 @@ | |
#include "ignition/gazebo/components/Sensor.hh" | ||
#include "ignition/gazebo/components/Visual.hh" | ||
#include "ignition/gazebo/components/World.hh" | ||
#include "ignition/gazebo/components/ParentEntity.hh" | ||
#include "ignition/gazebo/components/Physics.hh" | ||
#include "ignition/gazebo/components/PhysicsCmd.hh" | ||
#include "ignition/gazebo/components/Recreate.hh" | ||
#include "ignition/gazebo/Events.hh" | ||
#include "ignition/gazebo/SdfEntityCreator.hh" | ||
#include "ignition/gazebo/Util.hh" | ||
|
@@ -820,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(); | ||
|
||
|
@@ -831,6 +837,12 @@ void SimulationRunner::Step(const UpdateInfo &_info) | |
// Handle pending systems | ||
this->ProcessSystemQueue(); | ||
|
||
// Handle entities that need to be recreated. | ||
// Put in a request to mark them as removed so that in the UpdateSystem call | ||
// the systems can remove them first before new ones are created. This is | ||
// so that we can recreate entities with the same name. | ||
this->ProcessRecreateEntitiesRemove(); | ||
|
||
// Update all the systems. | ||
this->UpdateSystems(); | ||
|
||
|
@@ -861,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(); | ||
|
||
|
@@ -1136,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(); | ||
|
@@ -1170,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); | ||
|
@@ -1179,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) | ||
|
@@ -1252,6 +1288,57 @@ void SimulationRunner::ProcessWorldControl() | |
this->worldControls.clear(); | ||
} | ||
|
||
///////////////////////////////////////////////// | ||
void SimulationRunner::ProcessRecreateEntitiesRemove() | ||
{ | ||
IGN_PROFILE("SimulationRunner::ProcessRecreateEntitiesRemove"); | ||
|
||
// store the original entities to recreate and put in request to remove them | ||
this->entityCompMgr.Each<components::Model, | ||
components::Recreate>( | ||
[&](const Entity &_entity, | ||
const components::Model *, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only models are being removed, can we document this? Maybe on the component? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added documentation in 14d78f3 |
||
const components::Recreate *)->bool | ||
{ | ||
this->entitiesToRecreate.insert(_entity); | ||
this->entityCompMgr.RequestRemoveEntity(_entity, true); | ||
return true; | ||
}); | ||
} | ||
|
||
///////////////////////////////////////////////// | ||
void SimulationRunner::ProcessRecreateEntitiesCreate() | ||
{ | ||
IGN_PROFILE("SimulationRunner::ProcessRecreateEntitiesCreate"); | ||
|
||
// clone the original entities | ||
std::set<Entity> entitiesToRemoveRecreateComp; | ||
for (auto & ent : this->entitiesToRecreate) | ||
{ | ||
auto nameComp = this->entityCompMgr.Component<components::Name>(ent); | ||
auto parentComp = | ||
this->entityCompMgr.Component<components::ParentEntity>(ent); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's safer to check that the entity indeed has a name and a parent. At There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added checks in 14d78f3 |
||
// set allowRenaming to false so the entities keep their original name | ||
Entity clonedEntity = this->entityCompMgr.Clone(ent, | ||
parentComp->Data(), nameComp->Data(), false); | ||
entitiesToRemoveRecreateComp.insert(clonedEntity); | ||
entitiesToRemoveRecreateComp.insert(ent); | ||
} | ||
|
||
// remove the Recreate component so they do not get recreated again in the | ||
// next iteration | ||
for (auto &ent : entitiesToRemoveRecreateComp) | ||
{ | ||
if (!this->entityCompMgr.RemoveComponent<components::Recreate>(ent)) | ||
{ | ||
ignerr << "Failed to remove Recreate component from entity[" | ||
<< ent << "]" << std::endl; | ||
} | ||
} | ||
|
||
this->entitiesToRecreate.clear(); | ||
} | ||
|
||
///////////////////////////////////////////////// | ||
bool SimulationRunner::Paused() const | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we document how the component is used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added documentation in 14d78f3