diff --git a/CMakeLists.txt b/CMakeLists.txt
index 64899d8cf6..8e01f53d83 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -134,7 +134,7 @@ set(IGN_RENDERING_VER ${ignition-rendering6_VERSION_MAJOR})
#--------------------------------------
# Find ignition-math
-ign_find_package(ignition-math6 REQUIRED COMPONENTS eigen3 VERSION 6.8)
+ign_find_package(ignition-math6 REQUIRED COMPONENTS eigen3 VERSION 6.9)
set(IGN_MATH_VER ${ignition-math6_VERSION_MAJOR})
#--------------------------------------
diff --git a/examples/worlds/spherical_coordinates.sdf b/examples/worlds/spherical_coordinates.sdf
new file mode 100644
index 0000000000..24492c8213
--- /dev/null
+++ b/examples/worlds/spherical_coordinates.sdf
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EARTH_WGS84
+ ENU
+ -22.9
+ -43.2
+ 0
+ 0
+
+
+
+
+
+
+
+ 3D View
+ false
+ docked
+
+
+ ogre2
+ scene
+ 0.4 0.4 0.4
+ 0.8 0.8 0.8
+ -6 0 6 0 0.5 0
+
+
+
+
+
+ docked
+
+
+
+
+
+
+
diff --git a/include/ignition/gazebo/Util.hh b/include/ignition/gazebo/Util.hh
index 758ac65c00..9b6f83b92a 100644
--- a/include/ignition/gazebo/Util.hh
+++ b/include/ignition/gazebo/Util.hh
@@ -238,6 +238,15 @@ namespace ignition
return changed;
}
+ /// \brief Get the spherical coordinates for an entity.
+ /// \param[in] _entity Entity whose coordinates we want.
+ /// \param[in] _ecm Entity component manager
+ /// \return The entity's latitude (deg), longitude (deg) and elevation (m).
+ /// If the entity doesn't have a pose, or the world's spherical coordinates
+ /// haven't been defined, this will return nullopt.
+ std::optional IGNITION_GAZEBO_VISIBLE sphericalCoordinates(
+ Entity _entity, const EntityComponentManager &_ecm);
+
/// \brief Environment variable holding resource paths.
const std::string kResourcePathEnv{"IGN_GAZEBO_RESOURCE_PATH"};
diff --git a/include/ignition/gazebo/World.hh b/include/ignition/gazebo/World.hh
index 55d98ea54b..9e6d8ccfb0 100644
--- a/include/ignition/gazebo/World.hh
+++ b/include/ignition/gazebo/World.hh
@@ -24,6 +24,7 @@
#include
#include
+#include
#include "ignition/gazebo/config.hh"
#include "ignition/gazebo/EntityComponentManager.hh"
@@ -116,11 +117,24 @@ namespace ignition
/// \brief Get atmosphere information.
/// \param[in] _ecm Entity-component manager.
- /// \return Magnetic field vector or nullopt if the entity does not
+ /// \return Atmosphere or nullopt if the entity does not
/// have a components::Atmosphere component.
public: std::optional Atmosphere(
const EntityComponentManager &_ecm) const;
+ /// \brief Get spherical coordinates for the world origin.
+ /// \param[in] _ecm Entity-component manager.
+ /// \return Spherical coordinates or nullopt if the entity does not
+ /// have a components::SphericalCoordinates component.
+ public: std::optional SphericalCoordinates(
+ const EntityComponentManager &_ecm) const;
+
+ /// \brief Set spherical coordinates for the world origin.
+ /// \param[in] _ecm Entity-component manager.
+ /// \param[in] _sphericalCoordinates New spherical coordinates.
+ public: void SetSphericalCoordinates(EntityComponentManager &_ecm,
+ const math::SphericalCoordinates &_sphericalCoordinates);
+
/// \brief Get the ID of a light entity which is an immediate child of
/// this world.
/// \param[in] _ecm Entity-component manager.
diff --git a/include/ignition/gazebo/components/Serialization.hh b/include/ignition/gazebo/components/Serialization.hh
index 7fd3ee7765..1c3e144033 100644
--- a/include/ignition/gazebo/components/Serialization.hh
+++ b/include/ignition/gazebo/components/Serialization.hh
@@ -25,6 +25,7 @@
#include
#include
+#include
// This header holds serialization operators which are shared among several
// components
@@ -35,6 +36,31 @@ namespace gazebo
{
// Inline bracket to help doxygen filtering.
inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
+namespace traits
+{
+ /// \brief Type trait that determines if an ignition::gazebo::convert from In
+ /// to Out is defined.
+ /// Usage:
+ /// \code
+ /// constexpr bool hasGazeboConvert =
+ /// HasGazeboConvert::value
+ /// \endcode
+ template
+ class HasGazeboConvert
+ {
+ private: template
+ static auto Test(int _test)
+ -> decltype(std::declval() =
+ ignition::gazebo::convert(std::declval()),
+ std::true_type());
+
+ private: template
+ static auto Test(...) -> std::false_type;
+
+ public: static constexpr bool value = // NOLINT
+ decltype(Test(true))::value;
+ };
+}
/// \brief A Serializer class is used to serialize and deserialize a component.
/// It is passed in as the third template parameter to components::Component.
/// Eg.
@@ -78,7 +104,16 @@ namespace serializers
public: static std::ostream &Serialize(std::ostream &_out,
const DataType &_data)
{
- auto msg = ignition::gazebo::convert(_data);
+ MsgType msg;
+ if constexpr (traits::HasGazeboConvert::value)
+ {
+ msg = ignition::gazebo::convert(_data);
+ }
+ else
+ {
+ msg = ignition::msgs::Convert(_data);
+ }
+
msg.SerializeToOstream(&_out);
return _out;
}
@@ -93,7 +128,14 @@ namespace serializers
MsgType msg;
msg.ParseFromIstream(&_in);
- _data = ignition::gazebo::convert(msg);
+ if constexpr (traits::HasGazeboConvert::value)
+ {
+ _data = ignition::gazebo::convert(msg);
+ }
+ else
+ {
+ _data = ignition::msgs::Convert(msg);
+ }
return _in;
}
};
diff --git a/include/ignition/gazebo/components/SphericalCoordinates.hh b/include/ignition/gazebo/components/SphericalCoordinates.hh
new file mode 100644
index 0000000000..93ebd43fa8
--- /dev/null
+++ b/include/ignition/gazebo/components/SphericalCoordinates.hh
@@ -0,0 +1,53 @@
+/*
+ * 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_SPHERICALCOORDINATES_HH_
+#define IGNITION_GAZEBO_COMPONENTS_SPHERICALCOORDINATES_HH_
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace ignition
+{
+namespace gazebo
+{
+// Inline bracket to help doxygen filtering.
+inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
+namespace serializers
+{
+ using SphericalCoordinatesSerializer =
+ serializers::ComponentToMsgSerializer;
+}
+
+namespace components
+{
+ /// \brief This component holds the spherical coordinates of the world origin.
+ using SphericalCoordinates =
+ Component;
+ IGN_GAZEBO_REGISTER_COMPONENT(
+ "ign_gazebo_components.SphericalCoordinates", SphericalCoordinates)
+}
+}
+}
+}
+
+#endif
diff --git a/src/LevelManager.cc b/src/LevelManager.cc
index 00f9e6c4ab..6aa156dacc 100644
--- a/src/LevelManager.cc
+++ b/src/LevelManager.cc
@@ -25,6 +25,7 @@
#include
#include
+#include
#include
#include "ignition/gazebo/Events.hh"
@@ -53,6 +54,7 @@
#include "ignition/gazebo/components/RenderEngineServerHeadless.hh"
#include "ignition/gazebo/components/RenderEngineServerPlugin.hh"
#include "ignition/gazebo/components/Scene.hh"
+#include "ignition/gazebo/components/SphericalCoordinates.hh"
#include "ignition/gazebo/components/Wind.hh"
#include "ignition/gazebo/components/World.hh"
@@ -185,6 +187,14 @@ void LevelManager::ReadLevelPerformerInfo()
components::Atmosphere(*this->runner->sdfWorld->Atmosphere()));
}
+ // spherical coordinates
+ if (this->runner->sdfWorld->SphericalCoordinates())
+ {
+ this->runner->entityCompMgr.CreateComponent(this->worldEntity,
+ components::SphericalCoordinates(
+ *this->runner->sdfWorld->SphericalCoordinates()));
+ }
+
// TODO(anyone) This should probably go somewhere else as it is a global
// constant.
const std::string kPluginName{"ignition::gazebo"};
diff --git a/src/SdfEntityCreator.cc b/src/SdfEntityCreator.cc
index 72a0588924..29b9b968b1 100644
--- a/src/SdfEntityCreator.cc
+++ b/src/SdfEntityCreator.cc
@@ -66,6 +66,7 @@
#include "ignition/gazebo/components/SelfCollide.hh"
#include "ignition/gazebo/components/Sensor.hh"
#include "ignition/gazebo/components/SourceFilePath.hh"
+#include "ignition/gazebo/components/SphericalCoordinates.hh"
#include "ignition/gazebo/components/Static.hh"
#include "ignition/gazebo/components/ThermalCamera.hh"
#include "ignition/gazebo/components/ThreadPitch.hh"
@@ -237,6 +238,13 @@ Entity SdfEntityCreator::CreateEntities(const sdf::World *_world)
components::Atmosphere(*_world->Atmosphere()));
}
+ // spherical coordinates
+ if (_world->SphericalCoordinates())
+ {
+ this->dataPtr->ecm->CreateComponent(worldEntity,
+ components::SphericalCoordinates(*_world->SphericalCoordinates()));
+ }
+
// Models
for (uint64_t modelIndex = 0; modelIndex < _world->ModelCount();
++modelIndex)
diff --git a/src/Util.cc b/src/Util.cc
index 9681512d85..ec6efd57dc 100644
--- a/src/Util.cc
+++ b/src/Util.cc
@@ -47,6 +47,7 @@
#include "ignition/gazebo/components/ParticleEmitter.hh"
#include "ignition/gazebo/components/Pose.hh"
#include "ignition/gazebo/components/Sensor.hh"
+#include "ignition/gazebo/components/SphericalCoordinates.hh"
#include "ignition/gazebo/components/Visual.hh"
#include "ignition/gazebo/components/World.hh"
@@ -554,6 +555,30 @@ std::string validTopic(const std::vector &_topics)
}
return std::string();
}
+
+//////////////////////////////////////////////////
+std::optional sphericalCoordinates(Entity _entity,
+ const EntityComponentManager &_ecm)
+{
+ auto sphericalCoordinatesComp =
+ _ecm.Component(
+ worldEntity(_entity, _ecm));
+ if (nullptr == sphericalCoordinatesComp)
+ {
+ return std::nullopt;
+ }
+
+ auto xyzPose = worldPose(_entity, _ecm);
+
+ // lat / lon / elevation in rad / rad / m
+ auto rad = sphericalCoordinatesComp->Data().PositionTransform(
+ xyzPose.Pos(),
+ math::SphericalCoordinates::LOCAL2,
+ math::SphericalCoordinates::SPHERICAL);
+
+ // Return degrees
+ return math::Vector3d(IGN_RTOD(rad.X()), IGN_RTOD(rad.Y()), rad.Z());
+}
}
}
}
diff --git a/src/World.cc b/src/World.cc
index 333a0f430c..2d1514f79c 100644
--- a/src/World.cc
+++ b/src/World.cc
@@ -15,6 +15,7 @@
*
*/
+#include
#include
#include "ignition/gazebo/components/Actor.hh"
@@ -25,6 +26,7 @@
#include "ignition/gazebo/components/Model.hh"
#include "ignition/gazebo/components/Name.hh"
#include "ignition/gazebo/components/ParentEntity.hh"
+#include "ignition/gazebo/components/SphericalCoordinates.hh"
#include "ignition/gazebo/components/World.hh"
#include "ignition/gazebo/World.hh"
@@ -91,6 +93,34 @@ std::optional World::Atmosphere(
return _ecm.ComponentData(this->dataPtr->id);
}
+//////////////////////////////////////////////////
+std::optional World::SphericalCoordinates(
+ const EntityComponentManager &_ecm) const
+{
+ return _ecm.ComponentData(
+ this->dataPtr->id);
+}
+
+//////////////////////////////////////////////////
+void World::SetSphericalCoordinates(EntityComponentManager &_ecm,
+ const math::SphericalCoordinates &_sphericalCoordinates)
+{
+ auto sphericalCoordinatesComp =
+ _ecm.Component(this->dataPtr->id);
+ if (!sphericalCoordinatesComp)
+ {
+ _ecm.CreateComponent(this->dataPtr->id,
+ components::SphericalCoordinates(_sphericalCoordinates));
+ return;
+ }
+
+ sphericalCoordinatesComp->SetData(_sphericalCoordinates,
+ [](const math::SphericalCoordinates &,
+ const math::SphericalCoordinates &){return false;});
+ _ecm.SetChanged(this->dataPtr->id,
+ components::SphericalCoordinates::typeId, ComponentState::OneTimeChange);
+}
+
//////////////////////////////////////////////////
std::optional World::Gravity(
const EntityComponentManager &_ecm) const
diff --git a/src/gui/plugins/component_inspector/ComponentInspector.cc b/src/gui/plugins/component_inspector/ComponentInspector.cc
index 3255416565..158dde677d 100644
--- a/src/gui/plugins/component_inspector/ComponentInspector.cc
+++ b/src/gui/plugins/component_inspector/ComponentInspector.cc
@@ -57,6 +57,7 @@
#include "ignition/gazebo/components/SelfCollide.hh"
#include "ignition/gazebo/components/Sensor.hh"
#include "ignition/gazebo/components/SourceFilePath.hh"
+#include "ignition/gazebo/components/SphericalCoordinates.hh"
#include "ignition/gazebo/components/Static.hh"
#include "ignition/gazebo/components/Visual.hh"
#include "ignition/gazebo/components/WindMode.hh"
@@ -267,6 +268,26 @@ void ignition::gazebo::setData(QStandardItem *_item, const sdf::Physics &_data)
}), ComponentsModel::RoleNames().key("data"));
}
+//////////////////////////////////////////////////
+template<>
+void ignition::gazebo::setData(QStandardItem *_item,
+ const math::SphericalCoordinates &_data)
+{
+ if (nullptr == _item)
+ return;
+
+ _item->setData(QString("SphericalCoordinates"),
+ ComponentsModel::RoleNames().key("dataType"));
+ _item->setData(QList({
+ QVariant(QString::fromStdString(math::SphericalCoordinates::Convert(
+ _data.Surface()))),
+ QVariant(_data.LatitudeReference().Degree()),
+ QVariant(_data.LongitudeReference().Degree()),
+ QVariant(_data.ElevationReference()),
+ QVariant(_data.HeadingOffset().Degree()),
+ }), ComponentsModel::RoleNames().key("data"));
+}
+
//////////////////////////////////////////////////
void ignition::gazebo::setUnit(QStandardItem *_item, const std::string &_unit)
{
@@ -695,6 +716,13 @@ void ComponentInspector::Update(const UpdateInfo &,
if (comp)
setData(item, comp->Data());
}
+ else if (typeId == components::SphericalCoordinates::typeId)
+ {
+ auto comp = _ecm.Component(
+ this->dataPtr->entity);
+ if (comp)
+ setData(item, comp->Data());
+ }
else if (typeId == components::WindMode::typeId)
{
auto comp = _ecm.Component(this->dataPtr->entity);
@@ -954,6 +982,44 @@ void ComponentInspector::OnPhysics(double _stepSize, double _realTimeFactor)
this->dataPtr->node.Request(physicsCmdService, req, cb);
}
+/////////////////////////////////////////////////
+void ComponentInspector::OnSphericalCoordinates(QString _surface,
+ double _latitude, double _longitude, double _elevation,
+ double _heading)
+{
+ if (_surface != QString("EARTH_WGS84"))
+ {
+ ignerr << "Surface [" << _surface.toStdString() << "] not supported."
+ << std::endl;
+ return;
+ }
+
+ std::function cb =
+ [](const msgs::Boolean &/*_rep*/, const bool _result)
+ {
+ if (!_result)
+ ignerr << "Error setting spherical coordinates." << std::endl;
+ };
+
+ msgs::SphericalCoordinates req;
+ req.set_surface_model(msgs::SphericalCoordinates::EARTH_WGS84);
+ req.set_latitude_deg(_latitude);
+ req.set_longitude_deg(_longitude);
+ req.set_elevation(_elevation);
+ req.set_heading_deg(_heading);
+
+ auto sphericalCoordsCmdService = "/world/" + this->dataPtr->worldName
+ + "/set_spherical_coordinates";
+ sphericalCoordsCmdService =
+ transport::TopicUtils::AsValidTopic(sphericalCoordsCmdService);
+ if (sphericalCoordsCmdService.empty())
+ {
+ ignerr << "Invalid spherical coordinates service" << std::endl;
+ return;
+ }
+ this->dataPtr->node.Request(sphericalCoordsCmdService, req, cb);
+}
+
/////////////////////////////////////////////////
bool ComponentInspector::NestedModel() const
{
diff --git a/src/gui/plugins/component_inspector/ComponentInspector.hh b/src/gui/plugins/component_inspector/ComponentInspector.hh
index 193f7b4ddd..18b0ef7d66 100644
--- a/src/gui/plugins/component_inspector/ComponentInspector.hh
+++ b/src/gui/plugins/component_inspector/ComponentInspector.hh
@@ -21,6 +21,9 @@
#include