diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 50809d736..6c477c407 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -114,6 +114,7 @@ function(ign_gui_add_plugin plugin_name) endfunction() # Plugins +add_subdirectory(camera_fps) add_subdirectory(camera_tracking) add_subdirectory(grid_config) add_subdirectory(image_display) diff --git a/src/plugins/camera_fps/CMakeLists.txt b/src/plugins/camera_fps/CMakeLists.txt new file mode 100644 index 000000000..0670014d1 --- /dev/null +++ b/src/plugins/camera_fps/CMakeLists.txt @@ -0,0 +1,9 @@ +ign_gui_add_plugin(CameraFps + SOURCES + CameraFps.cc + QT_HEADERS + CameraFps.hh + PUBLIC_LINK_LIBS + ignition-rendering${IGN_RENDERING_VER}::ignition-rendering${IGN_RENDERING_VER} +) + diff --git a/src/plugins/camera_fps/CameraFps.cc b/src/plugins/camera_fps/CameraFps.cc new file mode 100644 index 000000000..c62a4efb4 --- /dev/null +++ b/src/plugins/camera_fps/CameraFps.cc @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2023 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 +#include + +#include +#include +#include +#include + +#include "ignition/gui/Application.hh" +#include "ignition/gui/GuiEvents.hh" +#include "ignition/gui/MainWindow.hh" + +#include "CameraFps.hh" + +/// \brief Private data class for CameraFps +class ignition::gui::plugins::CameraFpsPrivate +{ + /// \brief Previous camera update time + public: std::optional + prevCameraUpdateTime; + + /// \brief A moving window of camera update times + public: std::list> cameraUpdateTimes; + + /// \brief Sum of all update times in the moving window + public: std::chrono::duration cameraUpdateTimeSum; + + /// \brief Size of camera update time window + /// \todo(anyone) make this configurable + public: unsigned int cameraFPSWindowSize = 20u; + + /// \brief Camera FPS string value + public: QString cameraFPSValue; +}; + +using namespace ignition; +using namespace gui; +using namespace plugins; + +///////////////////////////////////////////////// +void CameraFps::OnRender() +{ + auto now = std::chrono::steady_clock::now(); + if (!this->dataPtr->prevCameraUpdateTime.has_value()) + { + this->dataPtr->prevCameraUpdateTime = now; + return; + } + + const std::chrono::duration dt = + std::chrono::steady_clock::now() - *this->dataPtr->prevCameraUpdateTime; + this->dataPtr->prevCameraUpdateTime = now; + this->dataPtr->cameraUpdateTimeSum += dt; + if (this->dataPtr->cameraUpdateTimes.size() >= + this->dataPtr->cameraFPSWindowSize) + { + auto first = this->dataPtr->cameraUpdateTimes.front(); + this->dataPtr->cameraUpdateTimes.pop_front(); + this->dataPtr->cameraUpdateTimeSum -= first; + double sum = this->dataPtr->cameraUpdateTimeSum.count(); + double avg = sum / + static_cast(this->dataPtr->cameraFPSWindowSize); + this->SetCameraFpsValue(QString::fromStdString(std::to_string(1.0/avg))); + } + this->dataPtr->cameraUpdateTimes.push_back(dt); +} + +///////////////////////////////////////////////// +CameraFps::CameraFps() + : Plugin(), dataPtr(new CameraFpsPrivate) +{ +} + +///////////////////////////////////////////////// +CameraFps::~CameraFps() +{ +} + +///////////////////////////////////////////////// +void CameraFps::LoadConfig(const tinyxml2::XMLElement *) +{ + if (this->title.empty()) + this->title = "Camera FPS"; + + App()->findChild()->installEventFilter(this); +} + +///////////////////////////////////////////////// +bool CameraFps::eventFilter(QObject *_obj, QEvent *_event) +{ + if (_event->type() == events::Render::kType) + { + this->OnRender(); + } + // Standard event processing + return QObject::eventFilter(_obj, _event); +} + +///////////////////////////////////////////////// +QString CameraFps::CameraFpsValue() const +{ + return this->dataPtr->cameraFPSValue; +} + +///////////////////////////////////////////////// +void CameraFps::SetCameraFpsValue(const QString &_value) +{ + this->dataPtr->cameraFPSValue = _value; + this->CameraFpsValueChanged(); +} + +// Register this plugin +IGNITION_ADD_PLUGIN(ignition::gui::plugins::CameraFps, + ignition::gui::Plugin) diff --git a/src/plugins/camera_fps/CameraFps.hh b/src/plugins/camera_fps/CameraFps.hh new file mode 100644 index 000000000..78a138579 --- /dev/null +++ b/src/plugins/camera_fps/CameraFps.hh @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 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 GZ_GUI_PLUGINS_CAMERAFPS_HH_ +#define GZ_GUI_PLUGINS_CAMERAFPS_HH_ + +#include + +#include "ignition/gui/Plugin.hh" + +namespace ignition +{ +namespace gui +{ +namespace plugins +{ + class CameraFpsPrivate; + + /// \brief This plugin displays the GUI camera's Framerate Per Second (FPS) + class CameraFps : public Plugin + { + Q_OBJECT + + /// \brief Camera frames per second + Q_PROPERTY( + QString cameraFPSValue + READ CameraFpsValue + WRITE SetCameraFpsValue + NOTIFY CameraFpsValueChanged + ) + + /// \brief Constructor + public: CameraFps(); + + /// \brief Destructor + public: virtual ~CameraFps(); + + // Documentation inherited + public: virtual void LoadConfig(const tinyxml2::XMLElement *_pluginElem) + override; + + /// \brief Set the camera FPS value string + /// \param[in] _value Camera FPS value string + public: Q_INVOKABLE void SetCameraFpsValue(const QString &_value); + + /// \brief Get the camera FPS value string + /// \return Camera FPS value string + public: Q_INVOKABLE QString CameraFpsValue() const; + + /// \brief Notify that camera FPS value has changed + signals: void CameraFpsValueChanged(); + + /// \brief Perform rendering calls in the rendering thread. + private: void OnRender(); + + // Documentation inherited + private: bool eventFilter(QObject *_obj, QEvent *_event) override; + + /// \internal + /// \brief Pointer to private data. + private: std::unique_ptr dataPtr; + }; +} +} +} +#endif diff --git a/src/plugins/camera_fps/CameraFps.qml b/src/plugins/camera_fps/CameraFps.qml new file mode 100644 index 000000000..87c42f9e6 --- /dev/null +++ b/src/plugins/camera_fps/CameraFps.qml @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2023 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.1 +import QtQuick.Layouts 1.3 + +Rectangle { + id: cameraFps + color: "transparent" + Layout.minimumWidth: 150 + Layout.minimumHeight: 80 + + RowLayout { + id: cameraFpsLayout + anchors.fill: parent + anchors.margins: 10 + + Label { + ToolTip.text: qsTr("Camera FPS") + font.weight: Font.DemiBold + text: "FPS" + } + + Label { + objectName: "cameraFps" + text: CameraFps.cameraFPSValue + Layout.alignment: Qt.AlignRight + } + } +} diff --git a/src/plugins/camera_fps/CameraFps.qrc b/src/plugins/camera_fps/CameraFps.qrc new file mode 100644 index 000000000..57549c350 --- /dev/null +++ b/src/plugins/camera_fps/CameraFps.qrc @@ -0,0 +1,5 @@ + + + CameraFps.qml + +