diff --git a/examples/worlds/gpu_lidar_retro_values_sensor.sdf b/examples/worlds/gpu_lidar_retro_values_sensor.sdf new file mode 100644 index 0000000000..f2d7a27c76 --- /dev/null +++ b/examples/worlds/gpu_lidar_retro_values_sensor.sdf @@ -0,0 +1,214 @@ + + + + + + 0.001 + 1.0 + + + + + ogre2 + + + + + + true + 0 0 10 0 0 0 + 0.8 0.8 0.8 1 + 0.2 0.2 0.2 1 + + 1000 + 0.9 + 0.01 + 0.001 + + -0.5 0.1 -0.9 + + + + true + + + + + + 20 20 0.1 + + + + + + + + 20 20 0.1 + + + + 0.8 0.8 0.8 1 + 0.8 0.8 0.8 1 + 0.8 0.8 0.8 1 + + + + + + + 0 -1 0.5 0 0 0 + + + + 1 + 0 + 0 + 1 + 0 + 1 + + 1.0 + + + + + 1 1 1 + + + + + + + + 1 1 1 + + + + 1 0 0 1 + 1 0 0 1 + 1 0 0 1 + + + + + + + 0 1 0.5 0 0 0 + + + + 1 + 0 + 0 + 1 + 0 + 1 + + 1.0 + + + + + 1 1 1 + + + + + + 500 + + + 1 1 1 + + + + 0 0 1 1 + 0 0 1 1 + 0 0 1 1 + + + + + + + 4 0 0.5 0 0.0 3.14 + + 0.05 0.05 0.05 0 0 0 + + 0.1 + + 0.000166667 + 0.000166667 + 0.000166667 + + + + + + 0.1 0.1 0.1 + + + + + + + 0.1 0.1 0.1 + + + + + + lidar + 10 + + + + 640 + 1 + -1.396263 + 1.396263 + + + 16 + 1 + -0.261799 + 0.261799 + + + + 0.08 + 10.0 + 0.01 + + + 1 + true + + + + true + + + + + diff --git a/include/ignition/gazebo/components/LaserRetro.hh b/include/ignition/gazebo/components/LaserRetro.hh new file mode 100644 index 0000000000..75d1145e92 --- /dev/null +++ b/include/ignition/gazebo/components/LaserRetro.hh @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 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_LASERRETRO_HH_ +#define IGNITION_GAZEBO_COMPONENTS_LASERRETRO_HH_ + +#include +#include +#include + +namespace ignition +{ +namespace gazebo +{ +// Inline bracket to help doxygen filtering. +inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { +namespace components +{ + /// \brief A component used to indicate an lidar reflective value + using LaserRetro = Component; + IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.LaserRetro", + LaserRetro) +} +} +} +} + +#endif diff --git a/src/SdfEntityCreator.cc b/src/SdfEntityCreator.cc index 3845830acb..ca14ac7c4b 100644 --- a/src/SdfEntityCreator.cc +++ b/src/SdfEntityCreator.cc @@ -41,6 +41,7 @@ #include "ignition/gazebo/components/Joint.hh" #include "ignition/gazebo/components/JointAxis.hh" #include "ignition/gazebo/components/JointType.hh" +#include "ignition/gazebo/components/LaserRetro.hh" #include "ignition/gazebo/components/Lidar.hh" #include "ignition/gazebo/components/Light.hh" #include "ignition/gazebo/components/LinearAcceleration.hh" @@ -503,6 +504,12 @@ Entity SdfEntityCreator::CreateEntities(const sdf::Visual *_visual) this->dataPtr->ecm->CreateComponent(visualEntity, components::Transparency(_visual->Transparency())); + if (_visual->HasLaserRetro()) + { + this->dataPtr->ecm->CreateComponent(visualEntity, + components::LaserRetro(_visual->LaserRetro())); + } + if (_visual->Geom()) { this->dataPtr->ecm->CreateComponent(visualEntity, diff --git a/src/SdfEntityCreator_TEST.cc b/src/SdfEntityCreator_TEST.cc index 94101b4b00..17e776b44d 100644 --- a/src/SdfEntityCreator_TEST.cc +++ b/src/SdfEntityCreator_TEST.cc @@ -35,6 +35,7 @@ #include "ignition/gazebo/components/Joint.hh" #include "ignition/gazebo/components/JointAxis.hh" #include "ignition/gazebo/components/JointType.hh" +#include "ignition/gazebo/components/LaserRetro.hh" #include "ignition/gazebo/components/Light.hh" #include "ignition/gazebo/components/Link.hh" #include "ignition/gazebo/components/Material.hh" @@ -101,6 +102,7 @@ TEST_F(SdfEntityCreatorTest, CreateEntities) EXPECT_TRUE(this->ecm.HasComponentType(components::Geometry::typeId)); EXPECT_TRUE(this->ecm.HasComponentType(components::Material::typeId)); EXPECT_TRUE(this->ecm.HasComponentType(components::Inertial::typeId)); + EXPECT_TRUE(this->ecm.HasComponentType(components::LaserRetro::typeId)); // Check entities // 1 x world + 3 x model + 3 x link + 3 x collision + 3 x visual + 1 x light @@ -356,6 +358,7 @@ TEST_F(SdfEntityCreatorTest, CreateEntities) unsigned int visualCount{0}; this->ecm.Eachecm.ParentEntity(_entity)); EXPECT_DOUBLE_EQ(0.0, _transparency->Data()); + EXPECT_DOUBLE_EQ(1150.0, _laserRetro->Data()); EXPECT_TRUE(_castShadows->Data()); EXPECT_EQ(sdf::GeometryType::BOX, _geometry->Data().Type()); @@ -417,6 +422,7 @@ TEST_F(SdfEntityCreatorTest, CreateEntities) EXPECT_EQ(cylLinkEntity, this->ecm.ParentEntity(_entity)); EXPECT_DOUBLE_EQ(0.0, _transparency->Data()); + EXPECT_DOUBLE_EQ(1654.0, _laserRetro->Data()); EXPECT_TRUE(_castShadows->Data()); EXPECT_EQ(sdf::GeometryType::CYLINDER, _geometry->Data().Type()); @@ -440,6 +446,7 @@ TEST_F(SdfEntityCreatorTest, CreateEntities) EXPECT_EQ(sphLinkEntity, this->ecm.ParentEntity(_entity)); EXPECT_DOUBLE_EQ(0.5, _transparency->Data()); + EXPECT_DOUBLE_EQ(50.0, _laserRetro->Data()); EXPECT_FALSE(_castShadows->Data()); EXPECT_EQ(sdf::GeometryType::SPHERE, _geometry->Data().Type()); diff --git a/src/gui/AboutDialogHandler.cc b/src/gui/AboutDialogHandler.cc new file mode 100644 index 0000000000..545f6fbb66 --- /dev/null +++ b/src/gui/AboutDialogHandler.cc @@ -0,0 +1,67 @@ +/* + * 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. + * + */ + +#include "AboutDialogHandler.hh" + +#include +#include +#include + +using namespace ignition; +using namespace gazebo; +using namespace gazebo::gui; + +///////////////////////////////////////////////// +AboutDialogHandler::AboutDialogHandler() +{ + aboutText += std::string(IGNITION_GAZEBO_VERSION_HEADER); + aboutText += "" + "" + "" + "" + "" + "" + "" + "" + "" + "
Documentation:" + "" + "" + "https://ignitionrobotics.org/libs/gazebo" + "" + "
" + "Tutorials:" + "" + "" + "https://ignitionrobotics.org/docs/" + "" + "
"; +} + +///////////////////////////////////////////////// +QString AboutDialogHandler::getVersionInformation() +{ + return QString::fromStdString(this->aboutText); +} + +///////////////////////////////////////////////// +void AboutDialogHandler::openURL(QString _url) +{ + QDesktopServices::openUrl(QUrl(_url)); +} diff --git a/src/gui/AboutDialogHandler.hh b/src/gui/AboutDialogHandler.hh new file mode 100644 index 0000000000..b5f71b543d --- /dev/null +++ b/src/gui/AboutDialogHandler.hh @@ -0,0 +1,58 @@ +/* + * 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_GUI_ABOUTDIALOGHANDLER_HH_ +#define IGNITION_GAZEBO_GUI_ABOUTDIALOGHANDLER_HH_ + +#include +#include +#include + +#include "ignition/gazebo/EntityComponentManager.hh" +#include "ignition/gazebo/Export.hh" + +namespace ignition +{ +namespace gazebo +{ +// Inline bracket to help doxygen filtering. +inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { +namespace gui +{ +/// \brief Class for handling about dialog +class IGNITION_GAZEBO_VISIBLE AboutDialogHandler : public QObject +{ + Q_OBJECT + + /// \brief Constructor + public: AboutDialogHandler(); + + /// \brief Get version information + /// \return Version information in rich text format + Q_INVOKABLE QString getVersionInformation(); + + /// \brief Function called from QML when user clicks on a link + /// \param[in] _url Url to web page. + Q_INVOKABLE void openURL(QString _url); + + /// \brief Version information and links to online resources + private: std::string aboutText; +}; +} +} +} +} +#endif diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 5d53622322..46d4be7f5c 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -1,4 +1,5 @@ set (gui_sources + AboutDialogHandler.cc Gui.cc GuiFileHandler.cc GuiRunner.cc diff --git a/src/gui/Gui.cc b/src/gui/Gui.cc index 00c3b7215f..04340d116d 100644 --- a/src/gui/Gui.cc +++ b/src/gui/Gui.cc @@ -28,6 +28,7 @@ #include "ignition/gazebo/gui/TmpIface.hh" #include "ignition/gazebo/gui/Gui.hh" +#include "AboutDialogHandler.hh" #include "GuiFileHandler.hh" #include "PathManager.hh" @@ -63,6 +64,9 @@ std::unique_ptr createGui( auto tmp = new ignition::gazebo::TmpIface(); tmp->setParent(app->Engine()); + auto aboutDialogHandler = new ignition::gazebo::gui::AboutDialogHandler(); + aboutDialogHandler->setParent(app->Engine()); + auto guiFileHandler = new ignition::gazebo::gui::GuiFileHandler(); guiFileHandler->setParent(app->Engine()); @@ -102,6 +106,7 @@ std::unique_ptr createGui( // Let QML files use TmpIface' functions and properties auto context = new QQmlContext(app->Engine()->rootContext()); context->setContextProperty("TmpIface", tmp); + context->setContextProperty("AboutDialogHandler", aboutDialogHandler); context->setContextProperty("GuiFileHandler", guiFileHandler); // Instantiate GazeboDrawer.qml file into a component diff --git a/src/gui/resources/GazeboDrawer.qml b/src/gui/resources/GazeboDrawer.qml index 8ca3f273a7..647883da34 100644 --- a/src/gui/resources/GazeboDrawer.qml +++ b/src/gui/resources/GazeboDrawer.qml @@ -60,6 +60,9 @@ Rectangle { case "loadWorld": loadWorldDialog.open(); break + case "aboutDialog": + aboutDialog.open(); + break // Forward others to default drawer default: parent.onAction(_action); @@ -73,46 +76,50 @@ Rectangle { // Custom action which calls custom C++ code /*ListElement { title: "New world" - action: "newWorld" + actionElement: "newWorld" type: "world" } ListElement { title: "Load world" - action: "loadWorld" + actionElement: "loadWorld" type: "world" }*/ ListElement { title: "Save world" - action: "saveWorld" + actionElement: "saveWorld" enabled: false type: "world" } ListElement { title: "Save world as..." - action: "saveWorldAs" + actionElement: "saveWorldAs" type: "world" } // Actions provided by Ignition GUI, with custom titles ListElement { title: "Load client configuration" - action: "loadConfig" + actionElement: "loadConfig" } ListElement { title: "Save client configuration" - action: "saveConfig" + actionElement: "saveConfig" } ListElement { title: "Save client configuration as" - action: "saveConfigAs" + actionElement: "saveConfigAs" } ListElement { title: "Style settings" - action: "styleSettings" + actionElement: "styleSettings" + } + ListElement { + title: "About" + actionElement: "aboutDialog" } ListElement { title: "Quit" - action: "close" + actionElement: "close" } } @@ -125,7 +132,7 @@ Rectangle { text: title highlighted: ListView.isCurrentItem onClicked: { - customDrawer.onAction(action); + customDrawer.onAction(actionElement); customDrawer.parent.closeDrawer(); } } @@ -165,6 +172,34 @@ Rectangle { } } + /** + * About dialog + */ + Dialog { + id: aboutDialog + title: "Ignition Gazebo" + + modal: true + focus: true + parent: ApplicationWindow.overlay + width: parent.width / 3 > 500 ? 500 : parent.width / 3 + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + closePolicy: Popup.CloseOnEscape + standardButtons: StandardButton.Ok + + Text { + anchors.fill: parent + id: aboutMessage + wrapMode: Text.Wrap + verticalAlignment: Text.AlignVCenter + color: Material.theme == Material.Light ? "black" : "white" + textFormat: Text.RichText + text: AboutDialogHandler.getVersionInformation() + onLinkActivated: AboutDialogHandler.openURL(link) + } + } + /** * Dialog with configurations for SDF generation */ diff --git a/src/rendering/RenderUtil.cc b/src/rendering/RenderUtil.cc index 1dde5ba785..43c2ca676c 100644 --- a/src/rendering/RenderUtil.cc +++ b/src/rendering/RenderUtil.cc @@ -48,6 +48,7 @@ #include "ignition/gazebo/components/DepthCamera.hh" #include "ignition/gazebo/components/GpuLidar.hh" #include "ignition/gazebo/components/Geometry.hh" +#include "ignition/gazebo/components/LaserRetro.hh" #include "ignition/gazebo/components/Light.hh" #include "ignition/gazebo/components/Link.hh" #include "ignition/gazebo/components/Material.hh" @@ -671,6 +672,12 @@ void RenderUtilPrivate::CreateRenderingEntities( visual.SetMaterial(material->Data()); } + auto laserRetro = _ecm.Component(_entity); + if (laserRetro != nullptr) + { + visual.SetLaserRetro(laserRetro->Data()); + } + // todo(anyone) make visual updates more generic without using extra // variables like entityTemp just for storing one specific visual // param? @@ -863,6 +870,12 @@ void RenderUtilPrivate::CreateRenderingEntities( visual.SetMaterial(material->Data()); } + auto laserRetro = _ecm.Component(_entity); + if (laserRetro != nullptr) + { + visual.SetLaserRetro(laserRetro->Data()); + } + this->newVisuals.push_back( std::make_tuple(_entity, visual, _parent->Data())); return true; diff --git a/src/rendering/SceneManager.cc b/src/rendering/SceneManager.cc index 0be6da0be2..41c8a5a81c 100644 --- a/src/rendering/SceneManager.cc +++ b/src/rendering/SceneManager.cc @@ -248,6 +248,11 @@ rendering::VisualPtr SceneManager::CreateVisual(Entity _id, visualVis->SetUserData("pause-update", static_cast(0)); visualVis->SetLocalPose(_visual.RawPose()); + if (_visual.HasLaserRetro()) + { + visualVis->SetUserData("laser_retro", _visual.LaserRetro()); + } + math::Vector3d scale = math::Vector3d::One; math::Pose3d localPose; rendering::GeometryPtr geom = @@ -258,17 +263,19 @@ rendering::VisualPtr SceneManager::CreateVisual(Entity _id, /// localPose is currently used to handle the normal vector in plane visuals /// In general, this can be used to store any local transforms between the /// parent Visual and geometry. - rendering::VisualPtr geomVis; if (localPose != math::Pose3d::Zero) { - geomVis = this->dataPtr->scene->CreateVisual(name + "_geom"); - geomVis->SetUserData("gazebo-entity", static_cast(_id)); - geomVis->SetUserData("pause-update", static_cast(0)); - geomVis->SetLocalPose(_visual.RawPose() * localPose); - visualVis = geomVis; + rendering::VisualPtr geomVis = + this->dataPtr->scene->CreateVisual(name + "_geom"); + geomVis->AddGeometry(geom); + geomVis->SetLocalPose(localPose); + visualVis->AddChild(geomVis); + } + else + { + visualVis->AddGeometry(geom); } - visualVis->AddGeometry(geom); visualVis->SetLocalScale(scale); // set material diff --git a/test/worlds/shapes.sdf b/test/worlds/shapes.sdf index ac254fa80b..dad5d0a8db 100644 --- a/test/worlds/shapes.sdf +++ b/test/worlds/shapes.sdf @@ -64,6 +64,7 @@ + 1150 0.12 0.12 0.12 0 0 0 @@ -105,6 +106,7 @@ + 1654 0.22 0.22 0.22 0 0 0 @@ -146,6 +148,7 @@ + 50 0.32 0.32 0.32 0 0 0 0.5 false