From 6f3f6db29f6d8c214b1d59b23c35119e397a16b0 Mon Sep 17 00:00:00 2001 From: Louise Poubel Date: Tue, 14 Jul 2020 18:48:59 -0700 Subject: [PATCH 1/2] Names with spaces: add string serializer Signed-off-by: Louise Poubel --- examples/worlds/fuel.sdf | 4 + include/ignition/gazebo/components/Actor.hh | 3 +- .../gazebo/components/ChildLinkName.hh | 6 +- .../gazebo/components/LevelEntityNames.hh | 14 +- include/ignition/gazebo/components/Name.hh | 4 +- .../gazebo/components/ParentLinkName.hh | 6 +- .../gazebo/components/PerformerAffinity.hh | 6 +- .../gazebo/components/PhysicsEnginePlugin.hh | 3 +- .../gazebo/components/Serialization.hh | 27 ++++ .../gazebo/components/SourceFilePath.hh | 4 +- test/integration/components.cc | 137 ++++++++++++++++-- 11 files changed, 188 insertions(+), 26 deletions(-) diff --git a/examples/worlds/fuel.sdf b/examples/worlds/fuel.sdf index 6dad7a8d24..14f07cd6f5 100644 --- a/examples/worlds/fuel.sdf +++ b/examples/worlds/fuel.sdf @@ -122,6 +122,7 @@ + Double pendulum -3 0 0 0 0 0 https://fuel.ignitionrobotics.org/1.0/nate/models/double_pendulum_with_base/2 @@ -134,12 +135,15 @@ + Gazebo (relative paths) 2 5 0 0 0 0 https://fuel.ignitionrobotics.org/1.0/chapulina/models/Gazebo - relative paths + Actor Test + 0 0 0 0 0 0 https://fuel.ignitionrobotics.org/1.0/chapulina/models/actor - relative paths diff --git a/include/ignition/gazebo/components/Actor.hh b/include/ignition/gazebo/components/Actor.hh index 526b96cecd..44d8bbc19c 100644 --- a/include/ignition/gazebo/components/Actor.hh +++ b/include/ignition/gazebo/components/Actor.hh @@ -86,7 +86,8 @@ namespace components AnimationTime) /// \brief Name of animation being currently played. - using AnimationName = Component; + using AnimationName = Component; IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.AnimationName", AnimationName) } diff --git a/include/ignition/gazebo/components/ChildLinkName.hh b/include/ignition/gazebo/components/ChildLinkName.hh index d9e2ff25b6..2381684d19 100644 --- a/include/ignition/gazebo/components/ChildLinkName.hh +++ b/include/ignition/gazebo/components/ChildLinkName.hh @@ -18,8 +18,9 @@ #define IGNITION_GAZEBO_COMPONENTS_CHILDLINKNAME_HH_ #include -#include #include +#include +#include #include namespace ignition @@ -32,7 +33,8 @@ namespace components { /// \brief A component used to indicate that a model is childlinkname (i.e. /// not moveable). - using ChildLinkName = Component; + using ChildLinkName = Component; IGN_GAZEBO_REGISTER_COMPONENT( "ign_gazebo_components.ChildLinkName", ChildLinkName) } diff --git a/include/ignition/gazebo/components/LevelEntityNames.hh b/include/ignition/gazebo/components/LevelEntityNames.hh index 9c45bc31a2..43324b08a7 100644 --- a/include/ignition/gazebo/components/LevelEntityNames.hh +++ b/include/ignition/gazebo/components/LevelEntityNames.hh @@ -43,9 +43,12 @@ namespace serializers public: static std::ostream &Serialize(std::ostream &_out, const std::set &_set) { + // Character to separate level names. It's the "Unit separator". + const char sep = 31; + for (const auto &entity : _set) { - _out << entity << " "; + _out << entity << sep; } return _out; } @@ -57,14 +60,13 @@ namespace serializers public: static std::istream &Deserialize(std::istream &_in, std::set &_set) { - _in.setf(std::ios_base::skipws); - _set.clear(); - for (auto it = std::istream_iterator(_in); - it != std::istream_iterator(); ++it) + const char sep = 31; + std::string level; + while (std::getline(_in, level, sep)) { - _set.insert(*it); + _set.insert(level); } return _in; } diff --git a/include/ignition/gazebo/components/Name.hh b/include/ignition/gazebo/components/Name.hh index 553be0b555..e41cc6fd8b 100644 --- a/include/ignition/gazebo/components/Name.hh +++ b/include/ignition/gazebo/components/Name.hh @@ -20,6 +20,7 @@ #include #include #include +#include #include namespace ignition @@ -32,7 +33,8 @@ namespace components { /// \brief This component holds an entity's name. The component has no concept /// of scoped names nor does it care about uniqueness. - using Name = Component; + using Name = Component; IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.Name", Name) } } diff --git a/include/ignition/gazebo/components/ParentLinkName.hh b/include/ignition/gazebo/components/ParentLinkName.hh index 6071431977..3081d163da 100644 --- a/include/ignition/gazebo/components/ParentLinkName.hh +++ b/include/ignition/gazebo/components/ParentLinkName.hh @@ -18,8 +18,9 @@ #define IGNITION_GAZEBO_COMPONENTS_PARENTLINKNAME_HH_ #include -#include #include +#include +#include #include namespace ignition @@ -31,7 +32,8 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { namespace components { /// \brief Holds the name of the entity's parent link. - using ParentLinkName = Component; + using ParentLinkName = Component; IGN_GAZEBO_REGISTER_COMPONENT( "ign_gazebo_components.ParentLinkName", ParentLinkName) } diff --git a/include/ignition/gazebo/components/PerformerAffinity.hh b/include/ignition/gazebo/components/PerformerAffinity.hh index acb439ef25..0afe760d0c 100644 --- a/include/ignition/gazebo/components/PerformerAffinity.hh +++ b/include/ignition/gazebo/components/PerformerAffinity.hh @@ -22,8 +22,9 @@ #include #include -#include "ignition/gazebo/components/Factory.hh" #include "ignition/gazebo/components/Component.hh" +#include "ignition/gazebo/components/Factory.hh" +#include "ignition/gazebo/components/Serialization.hh" namespace ignition { @@ -35,7 +36,8 @@ namespace components { /// \brief This component holds the address of the distributed secondary that /// this performer is associated with. - using PerformerAffinity = Component; + using PerformerAffinity = Component; IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.PerformerAffinity", PerformerAffinity) } diff --git a/include/ignition/gazebo/components/PhysicsEnginePlugin.hh b/include/ignition/gazebo/components/PhysicsEnginePlugin.hh index 2e5d5cbf73..dda8fa86df 100644 --- a/include/ignition/gazebo/components/PhysicsEnginePlugin.hh +++ b/include/ignition/gazebo/components/PhysicsEnginePlugin.hh @@ -20,6 +20,7 @@ #include #include #include +#include #include namespace ignition @@ -32,7 +33,7 @@ namespace components { /// \brief Holds the physics engine shared library. using PhysicsEnginePlugin = Component; + class PhysicsEnginePluginTag, serializers::StringSerializer>; IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.PhysicsEnginePlugin", PhysicsEnginePlugin) } diff --git a/include/ignition/gazebo/components/Serialization.hh b/include/ignition/gazebo/components/Serialization.hh index f6e223bd66..5fe9999dce 100644 --- a/include/ignition/gazebo/components/Serialization.hh +++ b/include/ignition/gazebo/components/Serialization.hh @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -156,6 +157,32 @@ namespace serializers return _in; } }; + + /// \brief Serializer for components that hold std::string. + class StringSerializer + { + /// \brief Serialization + /// \param[in] _out Output stream. + /// \param[in] _data Data to serialize. + /// \return The stream. + public: static std::ostream &Serialize(std::ostream &_out, + const std::string &_data) + { + _out << _data; + return _out; + } + + /// \brief Deserialization + /// \param[in] _in Input stream. + /// \param[in] _data Data to populate. + /// \return The stream. + public: static std::istream &Deserialize(std::istream &_in, + std::string &_data) + { + _data = std::string(std::istreambuf_iterator(_in), {}); + return _in; + } + }; } } } diff --git a/include/ignition/gazebo/components/SourceFilePath.hh b/include/ignition/gazebo/components/SourceFilePath.hh index 96cd30ebbb..d5919e1a43 100644 --- a/include/ignition/gazebo/components/SourceFilePath.hh +++ b/include/ignition/gazebo/components/SourceFilePath.hh @@ -20,6 +20,7 @@ #include #include #include +#include #include namespace ignition @@ -33,7 +34,8 @@ namespace components /// \brief This component holds the filepath to the source from which an /// entity is created. For example, it can be used to store the file path of a /// model's SDFormat file. - using SourceFilePath = Component; + using SourceFilePath = Component; IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.SourceFilePath", SourceFilePath) diff --git a/test/integration/components.cc b/test/integration/components.cc index 7c6e5aab9e..2f99c6d4ef 100644 --- a/test/integration/components.cc +++ b/test/integration/components.cc @@ -60,10 +60,13 @@ #include "ignition/gazebo/components/ParentEntity.hh" #include "ignition/gazebo/components/ParentLinkName.hh" #include "ignition/gazebo/components/Performer.hh" +#include "ignition/gazebo/components/PerformerAffinity.hh" #include "ignition/gazebo/components/PerformerLevels.hh" +#include "ignition/gazebo/components/PhysicsEnginePlugin.hh" #include "ignition/gazebo/components/Pose.hh" #include "ignition/gazebo/components/Scene.hh" #include "ignition/gazebo/components/Sensor.hh" +#include "ignition/gazebo/components/SourceFilePath.hh" #include "ignition/gazebo/components/Static.hh" #include "ignition/gazebo/components/ThreadPitch.hh" #include "ignition/gazebo/components/Visual.hh" @@ -110,6 +113,33 @@ TEST_F(ComponentsTest, Actor) EXPECT_EQ(ignition::math::Pose3d(3, 2, 1, 0, 0, 0), comp3.Data().RawPose()); } +///////////////////////////////////////////////// +TEST_F(ComponentsTest, AnimationName) +{ + // Create components + auto comp11 = components::AnimationName("comp1"); + auto comp12 = components::AnimationName("comp1"); + auto comp2 = components::AnimationName("comp2"); + + // Equality operators + EXPECT_EQ(comp11, comp12); + EXPECT_NE(comp11, comp2); + EXPECT_TRUE(comp11 == comp12); + EXPECT_TRUE(comp11 != comp2); + EXPECT_FALSE(comp11 == comp2); + EXPECT_FALSE(comp11 != comp12); + + // Stream operators + std::ostringstream ostr; + comp11.Serialize(ostr); + EXPECT_EQ("comp1", ostr.str()); + + std::istringstream istr("comp3"); + components::AnimationName comp3; + comp3.Deserialize(istr); + EXPECT_EQ("comp3", comp3.Data()); +} + ///////////////////////////////////////////////// TEST_F(ComponentsTest, AirPressureSensor) { @@ -664,9 +694,9 @@ TEST_F(ComponentsTest, LevelEntityNames) // Stream operators std::ostringstream ostr; comp11.Serialize(ostr); - EXPECT_EQ("level1 level2 ", ostr.str()); + EXPECT_EQ("level1\x1Flevel2\x1F", ostr.str()); - std::istringstream istr("level3 level4"); + std::istringstream istr("level3\x1Flevel4"); components::LevelEntityNames comp3; comp3.Deserialize(istr); @@ -945,14 +975,26 @@ TEST_F(ComponentsTest, Name) EXPECT_FALSE(comp11 != comp12); // Stream operators - std::ostringstream ostr; - comp11.Serialize(ostr); - EXPECT_EQ("comp1", ostr.str()); - - std::istringstream istr("comp3"); - components::Name comp3; - comp3.Deserialize(istr); - EXPECT_EQ("comp3", comp3.Data()); + for (auto str : { + "boring", + "snake_case", + "camelCase", + "with s p a c e s 123", + "with/slash", + "tópico", + "トピック" + }) + { + auto compA = components::Name(str); + std::ostringstream ostr; + compA.Serialize(ostr); + EXPECT_EQ(str, ostr.str()); + + std::istringstream istr(str); + components::Name compB; + compB.Deserialize(istr); + EXPECT_EQ(str, compB.Data()); + } } ///////////////////////////////////////////////// @@ -1031,6 +1073,33 @@ TEST_F(ComponentsTest, Performer) comp3.Deserialize(istr); } +///////////////////////////////////////////////// +TEST_F(ComponentsTest, PerformerAffinity) +{ + // Create components + auto comp11 = components::PerformerAffinity("comp1"); + auto comp12 = components::PerformerAffinity("comp1"); + auto comp2 = components::PerformerAffinity("comp2"); + + // Equality operators + EXPECT_EQ(comp11, comp12); + EXPECT_NE(comp11, comp2); + EXPECT_TRUE(comp11 == comp12); + EXPECT_TRUE(comp11 != comp2); + EXPECT_FALSE(comp11 == comp2); + EXPECT_FALSE(comp11 != comp12); + + // Stream operators + std::ostringstream ostr; + comp11.Serialize(ostr); + EXPECT_EQ("comp1", ostr.str()); + + std::istringstream istr("comp3"); + components::PerformerAffinity comp3; + comp3.Deserialize(istr); + EXPECT_EQ("comp3", comp3.Data()); +} + ///////////////////////////////////////////////// TEST_F(ComponentsTest, PerformerLevels) { @@ -1057,6 +1126,27 @@ TEST_F(ComponentsTest, PerformerLevels) EXPECT_EQ(0u, comp3.Data().count(1)); } +///////////////////////////////////////////////// +TEST_F(ComponentsTest, PhysicsEnginePlugin) +{ + // Create components + auto comp11 = components::PhysicsEnginePlugin("engine-plugin"); + auto comp12 = components::PhysicsEnginePlugin("engine-plugin"); + auto comp2 = components::PhysicsEnginePlugin("another-engine-plugin"); + + // TODO(anyone) Equality operators + + // Stream operators + std::ostringstream ostr; + comp11.Serialize(ostr); + EXPECT_EQ("engine-plugin", ostr.str()); + + std::istringstream istr("libengine-plugin.so"); + components::PhysicsEnginePlugin comp3; + comp3.Deserialize(istr); + EXPECT_EQ("libengine-plugin.so", comp3.Data()); +} + ///////////////////////////////////////////////// TEST_F(ComponentsTest, Pose) { @@ -1106,6 +1196,33 @@ TEST_F(ComponentsTest, Sensor) comp3.Deserialize(istr); } +///////////////////////////////////////////////// +TEST_F(ComponentsTest, SourceFilePath) +{ + // Create components + auto comp11 = components::SourceFilePath("comp1"); + auto comp12 = components::SourceFilePath("comp1"); + auto comp2 = components::SourceFilePath("comp2"); + + // Equality operators + EXPECT_EQ(comp11, comp12); + EXPECT_NE(comp11, comp2); + EXPECT_TRUE(comp11 == comp12); + EXPECT_TRUE(comp11 != comp2); + EXPECT_FALSE(comp11 == comp2); + EXPECT_FALSE(comp11 != comp12); + + // Stream operators + std::ostringstream ostr; + comp11.Serialize(ostr); + EXPECT_EQ("comp1", ostr.str()); + + std::istringstream istr("comp3"); + components::SourceFilePath comp3; + comp3.Deserialize(istr); + EXPECT_EQ("comp3", comp3.Data()); +} + ///////////////////////////////////////////////// TEST_F(ComponentsTest, Static) { From 652f8d5d8a2bfbbd24ce99715fbaab88ee701ede Mon Sep 17 00:00:00 2001 From: Louise Poubel Date: Fri, 17 Jul 2020 17:56:55 -0700 Subject: [PATCH 2/2] changelog Signed-off-by: Louise Poubel --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index c9a3d9721a..c55bbe51f0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,9 @@ ### Ignition Gazebo 4.0.0 (20XX-XX-XX) +1. Names with spaces: add string serializer + * [pull request 244](https://github.com/ignitionrobotics/ign-gazebo/pull/244) + 1. Filter mesh collision based on `collide_bitmask` property * [pull request 160](https://github.com/ignitionrobotics/ign-gazebo/pull/160)