Skip to content

Commit

Permalink
Examples and tutorial on using rendering API from plugins (#596)
Browse files Browse the repository at this point in the history
Signed-off-by: Louise Poubel <[email protected]>

Edifice to Citadel (#945)

Signed-off-by: Louise Poubel <[email protected]>
  • Loading branch information
chapulina committed Jul 30, 2021
1 parent fcfef74 commit 5cc6507
Show file tree
Hide file tree
Showing 17 changed files with 870 additions and 15 deletions.
4 changes: 2 additions & 2 deletions examples/plugin/custom_component/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ See `CustomComponentPlugin.hh` for more information.
From the root of the `ign-gazebo` repository, do the following to build the example:

~~~
cd ign-gazebo/examples/plugins/custom_component
cd examples/plugin/custom_component
mkdir build
cd build
cmake ..
Expand All @@ -23,7 +23,7 @@ This will generate the `CustomComponent` library under `build`.
Add the library to the path:

~~~
cd ign-gazebo/examples/plugins/custom_component
cd examples/plugin/custom_component
export IGN_GAZEBO_SYSTEM_PLUGIN_PATH=`pwd`/build
~~~

Expand Down
4 changes: 2 additions & 2 deletions examples/plugin/gui_system_plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See `GuiSystemPluginPlugin.hh` for more information.
From the root of the `ign-gazebo` repository, do the following to build the example:

~~~
cd ign-gazebo/examples/plugins/gui_system_plugin
cd examples/plugin/gui_system_plugin
mkdir build
cd build
cmake ..
Expand All @@ -28,7 +28,7 @@ This will generate the `GuiSystemPlugin` library under `build`.
Add the library to the path:

~~~
cd ign-gazebo/examples/plugins/gui_system_plugin
cd examples/plugin/gui_system_plugin
export IGN_GUI_PLUGIN_PATH=`pwd`/build
~~~

Expand Down
44 changes: 44 additions & 0 deletions examples/plugin/rendering_plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)

if(POLICY CMP0100)
cmake_policy(SET CMP0100 NEW)
endif()

project(RenderingPlugins)

# Common to both plugins
find_package(ignition-rendering3 REQUIRED)

# GUI plugin
set(GUI_PLUGIN RenderingGuiPlugin)

set(CMAKE_AUTOMOC ON)

find_package(ignition-gui3 REQUIRED)

QT5_ADD_RESOURCES(resources_RCC ${GUI_PLUGIN}.qrc)

add_library(${GUI_PLUGIN} SHARED
${GUI_PLUGIN}.cc
${resources_RCC}
)
target_link_libraries(${GUI_PLUGIN}
PRIVATE
ignition-gui3::ignition-gui3
ignition-rendering3::ignition-rendering3
)

# Server plugin
set(SERVER_PLUGIN RenderingServerPlugin)

find_package(ignition-plugin1 REQUIRED COMPONENTS register)
find_package(ignition-gazebo3 REQUIRED)

add_library(${SERVER_PLUGIN} SHARED ${SERVER_PLUGIN}.cc)
set_property(TARGET ${SERVER_PLUGIN} PROPERTY CXX_STANDARD 17)
target_link_libraries(${SERVER_PLUGIN}
PRIVATE
ignition-plugin1::ignition-plugin1
ignition-gazebo3::ignition-gazebo3
ignition-rendering3::ignition-rendering3
)
38 changes: 38 additions & 0 deletions examples/plugin/rendering_plugins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Rendering plugins

Demo of 2 plugins that use Ignition Rendering, one for the server and one for the client.

## Build

From the root of the `ign-gazebo` repository, do the following to build the example:

~~~
cd examples/plugin/rendering_plugins
mkdir build
cd build
cmake ..
make
~~~

This will generate the `RenderingGuiPlugin` and `RenderingServerPlugin` libraries under `build`.

## Run

Add the libraries to the correct paths:

~~~
cd examples/plugin/rendering_plugins
export IGN_GUI_PLUGIN_PATH=`pwd`/build
export IGN_GAZEBO_SYSTEM_PLUGIN_PATH=`pwd`/build
~~~

Run the example world

~~~
cd examples/plugin/rendering_plugins
ign gazebo -v 4 -r rendering_plugins.sdf
~~~

The ambient light on the server scene, visible from the camera sensor, will change every 2 seconds.

The ambient light on the client scene, visible from the GUI, will change every time the button is pressed.
145 changes: 145 additions & 0 deletions examples/plugin/rendering_plugins/RenderingGuiPlugin.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* 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 <ignition/gui/Application.hh>
//! [includeGuiEvents]
#include <ignition/gui/GuiEvents.hh>
//! [includeGuiEvents]
#include <ignition/gui/MainWindow.hh>
#include <ignition/math/Rand.hh>
#include <ignition/plugin/Register.hh>
#include <ignition/rendering/RenderEngine.hh>
#include <ignition/rendering/RenderingIface.hh>
#include <ignition/rendering/Scene.hh>

#include "RenderingGuiPlugin.hh"

/////////////////////////////////////////////////
void RenderingGuiPlugin::LoadConfig(const tinyxml2::XMLElement * /*_pluginElem*/)
{
// This is necessary to receive the Render event on eventFilter
//! [connectToGuiEvent]
ignition::gui::App()->findChild<
ignition::gui::MainWindow *>()->installEventFilter(this);
//! [connectToGuiEvent]
}

/////////////////////////////////////////////////
void RenderingGuiPlugin::RandomColor()
{
this->dirty = true;
}

/////////////////////////////////////////////////
//! [eventFilter]
bool RenderingGuiPlugin::eventFilter(QObject *_obj, QEvent *_event)
{
if (_event->type() == ignition::gui::events::Render::kType)
{
// This event is called in the render thread, so it's safe to make
// rendering calls here
this->PerformRenderingOperations();
}

// Standard event processing
return QObject::eventFilter(_obj, _event);
}
//! [eventFilter]

/////////////////////////////////////////////////
//! [performRenderingOperations]
void RenderingGuiPlugin::PerformRenderingOperations()
{
if (!this->dirty)
{
return;
}

if (nullptr == this->scene)
{
this->FindScene();
}

if (nullptr == this->scene)
return;

this->scene->SetAmbientLight({
static_cast<float>(ignition::math::Rand::DblUniform(0.0, 1.0)),
static_cast<float>(ignition::math::Rand::DblUniform(0.0, 1.0)),
static_cast<float>(ignition::math::Rand::DblUniform(0.0, 1.0)),
1.0});

this->dirty = false;
}
//! [performRenderingOperations]

/////////////////////////////////////////////////
void RenderingGuiPlugin::FindScene()
{
auto loadedEngNames = ignition::rendering::loadedEngines();
if (loadedEngNames.empty())
{
igndbg << "No rendering engine is loaded yet" << std::endl;
return;
}

// assume there is only one engine loaded
auto engineName = loadedEngNames[0];
if (loadedEngNames.size() > 1)
{
igndbg << "More than one engine is available. "
<< "Using engine [" << engineName << "]" << std::endl;
}
auto engine = ignition::rendering::engine(engineName);
if (!engine)
{
ignerr << "Internal error: failed to load engine [" << engineName
<< "]. Grid plugin won't work." << std::endl;
return;
}

if (engine->SceneCount() == 0)
{
igndbg << "No scene has been created yet" << std::endl;
return;
}

// Get first scene
auto scenePtr = engine->SceneByIndex(0);
if (nullptr == scenePtr)
{
ignerr << "Internal error: scene is null." << std::endl;
return;
}

if (engine->SceneCount() > 1)
{
igndbg << "More than one scene is available. "
<< "Using scene [" << scene->Name() << "]" << std::endl;
}

if (!scenePtr->IsInitialized() || nullptr == scenePtr->RootVisual())
{
return;
}

this->scene = scenePtr;
}

// Register this plugin
IGNITION_ADD_PLUGIN(RenderingGuiPlugin,
ignition::gui::Plugin)
57 changes: 57 additions & 0 deletions examples/plugin/rendering_plugins/RenderingGuiPlugin.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 RENDERING_GUI_PLUGIN_HH_
#define RENDERING_GUI_PLUGIN_HH_

#include <ignition/gui/qt.h>
#include <ignition/gui/Plugin.hh>
#include <ignition/rendering/Scene.hh>

/// \brief Example of a GUI plugin that uses Ignition Rendering.
/// This plugin works with either Ignition GUI's Scene3D or Ignition Gazebo's
/// Scene3D.
class RenderingGuiPlugin : public ignition::gui::Plugin
{
Q_OBJECT

///\brief Called once at startup.
public: void LoadConfig(const tinyxml2::XMLElement *) override;

/// \brief Callback when user clicks button.
public slots: void RandomColor();

/// \brief Callback for all installed event filters.
/// \param[in] _obj Object that received the event
/// \param[in] _event Event
private: bool eventFilter(QObject *_obj, QEvent *_event) override;

/// \brief All rendering operations must happen within this call
private: void PerformRenderingOperations();

/// \brief Encapsulates the logic to find the rendering scene through the
/// render engine singleton.
private: void FindScene();

/// \brief Marks when a new change has been requested.
private: bool dirty{false};

/// \brief Pointer to the rendering scene.
private: ignition::rendering::ScenePtr scene{nullptr};
};

#endif
34 changes: 34 additions & 0 deletions examples/plugin/rendering_plugins/RenderingGuiPlugin.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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.
*
*/
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3

Rectangle {
color: "transparent"
anchors.fill: parent
Layout.minimumWidth: 250
Layout.minimumHeight: 100
Button {
text: qsTr("Random GUI color!")
onClicked: {
RenderingGuiPlugin.RandomColor();
}
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
5 changes: 5 additions & 0 deletions examples/plugin/rendering_plugins/RenderingGuiPlugin.qrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="RenderingGuiPlugin/">
<file>RenderingGuiPlugin.qml</file>
</qresource>
</RCC>
Loading

0 comments on commit 5cc6507

Please sign in to comment.