diff --git a/src/systems/scene_broadcaster/SceneBroadcaster.cc b/src/systems/scene_broadcaster/SceneBroadcaster.cc index 91cdf15e34..a8c5d2d857 100644 --- a/src/systems/scene_broadcaster/SceneBroadcaster.cc +++ b/src/systems/scene_broadcaster/SceneBroadcaster.cc @@ -49,6 +49,7 @@ #include "ignition/gazebo/components/Model.hh" #include "ignition/gazebo/components/Name.hh" #include "ignition/gazebo/components/ParentEntity.hh" +#include "ignition/gazebo/components/ParticleEmitter.hh" #include "ignition/gazebo/components/Pose.hh" #include "ignition/gazebo/components/RgbdCamera.hh" #include "ignition/gazebo/components/Scene.hh" @@ -156,6 +157,15 @@ class ignition::gazebo::systems::SceneBroadcasterPrivate public: static void AddSensors(msgs::Link *_msg, const Entity _entity, const SceneGraphType &_graph); + /// \brief Adds particle emitters to a msgs::Link object based on the + /// contents of the scene graph + /// \param[inout] _msg Pointer to msg object to which the particle + /// emitters will be added. + /// \param[in] _entity Parent entity in the graph + /// \param[in] _graph Scene graph + public: static void AddParticleEmitters(msgs::Link *_msg, + const Entity _entity, const SceneGraphType &_graph); + /// \brief Recursively remove entities from the graph /// \param[in] _entity Entity /// \param[in/out] _graph Scene graph @@ -995,6 +1005,26 @@ void SceneBroadcasterPrivate::SceneGraphAddEntities( return true; }); + // Particle emitters + _manager.EachNew( + [&](const Entity &_entity, + const components::ParticleEmitter *_emitterComp, + const components::ParentEntity *_parentComp, + const components::Pose *_poseComp) -> bool + { + auto emitterMsg = std::make_shared(); + emitterMsg->CopyFrom(_emitterComp->Data()); + emitterMsg->set_id(_entity); + emitterMsg->mutable_pose()->CopyFrom(msgs::Convert(_poseComp->Data())); + + // Add to graph + newGraph.AddVertex(emitterMsg->name(), emitterMsg, _entity); + newGraph.AddEdge({_parentComp->Data(), _entity}, true); + newEntity = true; + return true; + }); + // Update the whole scene graph from the new graph { std::lock_guard lock(this->graphMutex); @@ -1158,6 +1188,24 @@ void SceneBroadcasterPrivate::AddSensors(msgs::Link *_msg, const Entity _entity, } } +////////////////////////////////////////////////// +void SceneBroadcasterPrivate::AddParticleEmitters(msgs::Link *_msg, + const Entity _entity, const SceneGraphType &_graph) +{ + if (!_msg) + return; + + for (const auto &vertex : _graph.AdjacentsFrom(_entity)) + { + auto emitterMsg = std::dynamic_pointer_cast( + vertex.second.get().Data()); + if (!emitterMsg) + continue; + + _msg->add_particle_emitter()->CopyFrom(*emitterMsg); + } +} + ////////////////////////////////////////////////// void SceneBroadcasterPrivate::AddLinks(msgs::Model *_msg, const Entity _entity, const SceneGraphType &_graph) @@ -1183,6 +1231,9 @@ void SceneBroadcasterPrivate::AddLinks(msgs::Model *_msg, const Entity _entity, // Sensors AddSensors(msgOut, vertex.second.get().Id(), _graph); + + // Particle emitters + AddParticleEmitters(msgOut, vertex.second.get().Id(), _graph); } } diff --git a/test/integration/scene_broadcaster_system.cc b/test/integration/scene_broadcaster_system.cc index 41ca64e113..878e200e73 100644 --- a/test/integration/scene_broadcaster_system.cc +++ b/test/integration/scene_broadcaster_system.cc @@ -952,6 +952,63 @@ TEST_P(SceneBroadcasterTest, EXPECT_FALSE(res.has_sky()); } +TEST_P(SceneBroadcasterTest, + IGN_UTILS_TEST_DISABLED_ON_WIN32(SceneInfoHasParticleEmitter)) +{ + // Start server + ignition::gazebo::ServerConfig serverConfig; + serverConfig.SetSdfFile(std::string(PROJECT_SOURCE_PATH) + + common::joinPaths("/", "test", "worlds", "particle_emitter2.sdf")); + + gazebo::Server server(serverConfig); + EXPECT_FALSE(server.Running()); + EXPECT_FALSE(*server.Running(0)); + + // Run server + server.Run(true, 1, false); + + // Create requester + transport::Node node; + + bool result{false}; + unsigned int timeout{5000}; + ignition::msgs::Scene res; + + EXPECT_TRUE(node.Request("/world/particle_emitters/scene/info", + timeout, res, result)); + ASSERT_TRUE(result); + + ASSERT_EQ(3, res.model_size()); + int count = 0; + for (int i = 0; i < res.model_size(); ++i) + { + if (res.model(i).name() == "smoke_generator_demo_model") + { + count++; + // There should be one link + ASSERT_EQ(1, res.model(i).link_size()); + // The link should have one particle emitter + ASSERT_EQ(1, res.model(i).link(0).particle_emitter_size()); + + // Check a few parameter values to make sure we have the correct + // particle emittter + const msgs::ParticleEmitter &emitter = + res.model(i).link(0).particle_emitter(0); + EXPECT_EQ("smoke_emitter", emitter.name()); + EXPECT_EQ(math::Pose3d(0, 1, 0, 0, 0, 0), msgs::Convert(emitter.pose())); + EXPECT_EQ(math::Vector3d(2, 2, 2), msgs::Convert(emitter.size())); + EXPECT_DOUBLE_EQ(5.0, emitter.rate().data()); + EXPECT_DOUBLE_EQ(1.0, emitter.duration().data()); + EXPECT_EQ(math::Vector3d(3, 3, 3), + msgs::Convert(emitter.particle_size())); + EXPECT_DOUBLE_EQ(2.0, emitter.lifetime().data()); + } + } + + // Should have found 1 particle emitter. + EXPECT_EQ(1, count); +} + // Run multiple times INSTANTIATE_TEST_SUITE_P(ServerRepeat, SceneBroadcasterTest, ::testing::Range(1, 2)); diff --git a/test/worlds/particle_emitter2.sdf b/test/worlds/particle_emitter2.sdf index ca643ae13e..8d374ceff7 100644 --- a/test/worlds/particle_emitter2.sdf +++ b/test/worlds/particle_emitter2.sdf @@ -11,6 +11,10 @@ filename="ignition-gazebo-particle-emitter2-system" name="ignition::gazebo::systems::ParticleEmitter2"> + + true