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)
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)
{