From 0a62a62ee6e46a9eb1dd8c43588dd105abff394a Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Mon, 12 Jun 2023 21:59:30 +0200 Subject: [PATCH 01/18] Find any major version of Protobuf (#544) Signed-off-by: Silvio Traversaro --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee7baf395..811fddcd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,9 +30,7 @@ message(STATUS "\n\n-- ====== Finding Dependencies ======") #-------------------------------------- # Find Protobuf -set(REQ_PROTOBUF_VER 3) ign_find_package(IgnProtobuf - VERSION ${REQ_PROTOBUF_VER} REQUIRED PRETTY Protobuf) From 196edbc01f10a1dc40c17b7b42c5b144a8580ba5 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Wed, 1 Nov 2023 16:57:02 -0700 Subject: [PATCH 02/18] Update github issue template (#591) Signed-off-by: Ian Chen --- .github/ISSUE_TEMPLATE/bug_report.md | 6 +++--- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8e30646e3..62e9a50bd 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -5,7 +5,7 @@ labels: bug --- +https://robotics.stackexchange.com instead.--> ## Environment * OS Version: @@ -47,9 +47,9 @@ http://answers.gazebosim.org instead.--> - On Mac OS, open a terminal and type `system_profiler SPDisplaysDataType`. Copy the output here. - [ ] Please, attach the ogre.log or ogre2.log file from `~/.ignition/rendering` - +
- + ``` # paste log here ``` diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 87233a479..52b56e336 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -6,7 +6,7 @@ labels: enhancement +https://robotics.stackexchange.com instead.--> ## Desired behavior From 2759bffae54e274de9959ddd0f9d8cf584a9191f Mon Sep 17 00:00:00 2001 From: Martin Pecka Date: Fri, 10 Nov 2023 16:29:45 +0100 Subject: [PATCH 03/18] Fix plugin filter on Windows (#567) Signed-off-by: Martin Pecka Signed-off-by: Jenn Nguyen <8602001+jennuine@users.noreply.github.com> Co-authored-by: Silvio Traversaro Co-authored-by: Ian Chen Co-authored-by: Jenn Nguyen <8602001+jennuine@users.noreply.github.com> Co-authored-by: Jenn Nguyen --- include/gz/gui/CMakeLists.txt | 4 ++++ src/Application.cc | 15 ++++++++++++--- src/MainWindow.cc | 9 +++++++-- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/gz/gui/CMakeLists.txt b/include/gz/gui/CMakeLists.txt index 27db7054e..ccf76a2da 100644 --- a/include/gz/gui/CMakeLists.txt +++ b/include/gz/gui/CMakeLists.txt @@ -75,5 +75,9 @@ target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME} TINYXML2::TINYXML2 ) +target_compile_definitions(${PROJECT_LIBRARY_TARGET_NAME} PRIVATE + SHARED_LIBRARY_PREFIX=\"${CMAKE_SHARED_LIBRARY_PREFIX}\" + SHARED_LIBRARY_SUFFIX=\"${CMAKE_SHARED_LIBRARY_SUFFIX}\") + gz_install_all_headers() diff --git a/src/Application.cc b/src/Application.cc index 6031e4c30..f1b3ffc4d 100644 --- a/src/Application.cc +++ b/src/Application.cc @@ -837,10 +837,19 @@ std::vector>> { auto plugin = common::basename(*dirIter); - // All we verify is that the file starts with "lib", any further - // checks would require loading the plugin. + // All we verify is that the file starts with shared library prefix and + // ends with shared library suffix, any further checks would require + // loading the plugin. - if (plugin.find("lib") == 0) + // TODO(anyone): Move this logic into gz-plugin to be reusable + + // This computation could underflow the unsigned range, but that is okay + // as in such case we would check if the suffix is placed somewhere much + // further than allowed filename length. + const auto suffixPos = plugin.length() - strlen(SHARED_LIBRARY_SUFFIX); + + if (plugin.find(SHARED_LIBRARY_PREFIX) == 0 && + plugin.rfind(SHARED_LIBRARY_SUFFIX) == suffixPos) ps.push_back(plugin); } diff --git a/src/MainWindow.cc b/src/MainWindow.cc index 234591ae2..37be9d851 100644 --- a/src/MainWindow.cc +++ b/src/MainWindow.cc @@ -126,8 +126,13 @@ QStringList MainWindow::PluginListModel() const { for (auto const &plugin : path.second) { - // Remove lib and .so - auto pluginName = plugin.substr(3, plugin.find(".") - 3); + // TODO(anyone): Move this into gz-plugin to be reusable + + // Remove shared library prefix and shared library suffix + auto pluginName = plugin.substr( + strlen(SHARED_LIBRARY_PREFIX), + plugin.length() - strlen(SHARED_LIBRARY_PREFIX) - + strlen(SHARED_LIBRARY_SUFFIX)); // Split WWWCamelCase3D -> WWW Camel Case 3D std::regex reg("(\\B[A-Z][a-z])|(\\B[0-9])"); From 43bfe9bd97fe0681da08a3e163155b95ba7f0617 Mon Sep 17 00:00:00 2001 From: "Addisu Z. Taddese" Date: Mon, 13 Nov 2023 16:46:52 -0600 Subject: [PATCH 04/18] Update github action workflows (#597) * Use on `push` only on stable branches to avoid duplicate runs * Update project automation Signed-off-by: Addisu Z. Taddese --- .github/workflows/ci.yml | 12 +++++++++--- .github/workflows/triage.yml | 9 +++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2e4d6192..a7b11a1ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,12 @@ name: Ubuntu CI -on: [push, pull_request] +on: + pull_request: + push: + branches: + - 'ign-gui[0-9]' + - 'gz-gui[0-9]?' + - 'main' jobs: bionic-ci: @@ -8,7 +14,7 @@ jobs: name: Ubuntu Bionic CI steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Compile and test id: ci uses: ignition-tooling/action-ignition-ci@bionic @@ -20,7 +26,7 @@ jobs: name: Ubuntu Focal CI steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Compile and test id: ci uses: ignition-tooling/action-ignition-ci@focal diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml index 736670e0e..2332244bf 100644 --- a/.github/workflows/triage.yml +++ b/.github/workflows/triage.yml @@ -10,10 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Add ticket to inbox - uses: technote-space/create-project-card-action@v1 + uses: actions/add-to-project@v0.5.0 with: - PROJECT: Core development - COLUMN: Inbox - GITHUB_TOKEN: ${{ secrets.TRIAGE_TOKEN }} - CHECK_ORG_PROJECT: true - + project-url: https://github.com/orgs/gazebosim/projects/7 + github-token: ${{ secrets.TRIAGE_TOKEN }} From 5674c036f4c4e38ddcf10b72027aaef60dc6234a Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Tue, 5 Dec 2023 20:47:04 +0000 Subject: [PATCH 05/18] Fix QImage's step size in ImageDisplay plugin Signed-off-by: Ian Chen --- src/plugins/image_display/ImageDisplay.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/image_display/ImageDisplay.cc b/src/plugins/image_display/ImageDisplay.cc index 5cd311d9a..7f0e78a18 100644 --- a/src/plugins/image_display/ImageDisplay.cc +++ b/src/plugins/image_display/ImageDisplay.cc @@ -129,7 +129,8 @@ void ImageDisplay::ProcessImage() case msgs::PixelFormatType::RGB_INT8: // copy image data buffer directly to QImage image = QImage(reinterpret_cast( - this->dataPtr->imageMsg.data().c_str()), width, height, qFormat); + this->dataPtr->imageMsg.data().c_str()), width, height, + 3 * width, qFormat); break; // for other cases, convert to RGB common::Image case msgs::PixelFormatType::R_FLOAT32: From d97c6a1c1222f8bd192743fec6e5f04df8e8c070 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 21 Dec 2023 07:28:07 -0800 Subject: [PATCH 06/18] Update CI badges in README (#603) Signed-off-by: Ian Chen --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4db88fa43..a0a011afe 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ Build | Status -- | -- -Test coverage | [![codecov](https://codecov.io/gh/gazebosim/gz-gui/branch/main/graph/badge.svg)](https://codecov.io/gh/gazebosim/gz-gui/branch/main) -Ubuntu Focal | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_gui-ci-main-focal-amd64)](https://build.osrfoundation.org/job/ignition_gui-ci-main-focal-amd64) -Homebrew | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_gui-ci-main-homebrew-amd64)](https://build.osrfoundation.org/job/ignition_gui-ci-main-homebrew-amd64) -Windows | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ign_gui-ci-win)](https://build.osrfoundation.org/job/ign_gui-ci-win) +Test coverage | [![codecov](https://codecov.io/gh/gazebosim/gz-gui/tree/gz-gui8/graph/badge.svg)](https://codecov.io/gh/gazebosim/gz-gui/tree/gz-gui8) +Ubuntu Jammy | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=gz_gui-ci-gz-gui8-jammy-amd64)](https://build.osrfoundation.org/job/gz_gui-ci-gz-gui8-jammy-amd64) +Homebrew | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=gz_gui-ci-gz-gui8-homebrew-amd64)](https://build.osrfoundation.org/job/gz_gui-ci-gz-gui8-homebrew-amd64) +Windows | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=gz_gui-8-win)](https://build.osrfoundation.org/job/gz_gui-8-win) Gazebo GUI builds on top of [Qt](https://www.qt.io/) to provide widgets which are useful when developing robotics applications, such as a 3D view, plots, dashboard, etc, From 125a5ea6d398d5870cca81403331d5c5ce09bbc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Fri, 2 Feb 2024 23:18:51 +0100 Subject: [PATCH 07/18] Forward port ci workflow changes. (#608) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6cd9b212..bdac4dc4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,12 @@ name: Ubuntu CI -on: [push, pull_request] +on: + pull_request: + push: + branches: + - 'ign-gui[0-9]' + - 'gz-gui[0-9]?' + - 'main' jobs: jammy-ci: From b252bd01c80ca6a03d6bdccb40497f70dbe6d3e9 Mon Sep 17 00:00:00 2001 From: "Addisu Z. Taddese" Date: Thu, 14 Mar 2024 19:33:39 -0500 Subject: [PATCH 08/18] Prepare for 8.1.0 (#612) Signed-off-by: Addisu Z. Taddese --- CMakeLists.txt | 2 +- Changelog.md | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d5c4b005b..5a8725885 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(gz-gui8 VERSION 8.0.0) +project(gz-gui8 VERSION 8.1.0) #============================================================================ # Find gz-cmake diff --git a/Changelog.md b/Changelog.md index 0c6a42cb8..33b15219e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,27 @@ ## Gazebo GUI 8 +### Gazebo GUI 8.1.0 (2024-03-14) + +1. Update CI badges in README + * [Pull request #603](https://github.com/gazebosim/gz-gui/pull/603) + +1. Fix plugin filter on Windows + * [Pull request #567](https://github.com/gazebosim/gz-gui/pull/567) + +1. Tidy namespaces + * [Pull request #590](https://github.com/gazebosim/gz-gui/pull/590) + +1. Infrastructure + * [Pull request #591](https://github.com/gazebosim/gz-gui/pull/591) + * [Pull request #597](https://github.com/gazebosim/gz-gui/pull/597) + * [Pull request #608](https://github.com/gazebosim/gz-gui/pull/608) + +1. Add check for vulkan support in rendering + * [Pull request #589](https://github.com/gazebosim/gz-gui/pull/589) + +1. Add optional binary relocatability + * [Pull request #580](https://github.com/gazebosim/gz-gui/pull/580) + ### Gazebo GUI 8.0.0 (2023-09-29) 1. Use fully-qualified message names to avoid deprecation warning From 648c8b7f1d5e4c38bbf3662734c7bcf7eb6cc7d0 Mon Sep 17 00:00:00 2001 From: "Addisu Z. Taddese" Date: Wed, 10 Apr 2024 16:57:30 -0500 Subject: [PATCH 09/18] Use relative install paths for plugin shared librariesi and gz-tools data (#614) Signed-off-by: Addisu Z. Taddese --- conf/CMakeLists.txt | 2 +- doc/CMakeLists.txt | 2 +- src/cmd/CMakeLists.txt | 2 +- src/plugins/CMakeLists.txt | 2 +- src/plugins/grid_config/CMakeLists.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/conf/CMakeLists.txt b/conf/CMakeLists.txt index 70201dfd8..4fb0a6a34 100644 --- a/conf/CMakeLists.txt +++ b/conf/CMakeLists.txt @@ -20,4 +20,4 @@ configure_file( # Install the yaml configuration files in an unversioned location. install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${GZ_DESIGNATION}${PROJECT_VERSION_MAJOR}.yaml - DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/gz/) + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gz/) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 0fd15b96c..7a1d464b3 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -25,5 +25,5 @@ if (DOXYGEN_FOUND) COMMENT "Generating API documentation with Doxygen" VERBATIM) install(FILES ${CMAKE_BINARY_DIR}/doc/${PROJECT_NAME_LOWER}.tag.xml - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/gz/${PROJECT_NAME_LOWER}_${PROJECT_VERSION_MINOR}) + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gz/${PROJECT_NAME_LOWER}_${PROJECT_VERSION_MINOR}) endif() diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt index 821cd4acf..568de6289 100644 --- a/src/cmd/CMakeLists.txt +++ b/src/cmd/CMakeLists.txt @@ -51,4 +51,4 @@ install( FILES ${CMAKE_CURRENT_BINARY_DIR}/gui${PROJECT_VERSION_MAJOR}.bash_completion.sh DESTINATION - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/gz/gz${GZ_TOOLS_VER}.completion.d) + ${CMAKE_INSTALL_DATAROOTDIR}/gz/gz${GZ_TOOLS_VER}.completion.d) diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 3f40148e9..01f7fc687 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -110,7 +110,7 @@ function(gz_gui_add_plugin plugin_name) COMPILE_FLAGS "/wd4251") endif() - install (TARGETS ${plugin_name} DESTINATION ${GZ_GUI_PLUGIN_INSTALL_DIR}) + install (TARGETS ${plugin_name} DESTINATION ${GZ_GUI_PLUGIN_RELATIVE_INSTALL_DIR}) endfunction() # Plugins diff --git a/src/plugins/grid_config/CMakeLists.txt b/src/plugins/grid_config/CMakeLists.txt index 101e6edee..5c2a3cb65 100644 --- a/src/plugins/grid_config/CMakeLists.txt +++ b/src/plugins/grid_config/CMakeLists.txt @@ -11,4 +11,4 @@ gz_gui_add_plugin(GridConfig install ( FILES $ RENAME ${CMAKE_SHARED_LIBRARY_PREFIX}Grid3D${CMAKE_SHARED_LIBRARY_SUFFIX} - DESTINATION ${GZ_GUI_PLUGIN_INSTALL_DIR}) + DESTINATION ${GZ_GUI_PLUGIN_RELATIVE_INSTALL_DIR}) From a4710e950ff27ba691779940c3fad179ca1ed3c7 Mon Sep 17 00:00:00 2001 From: Jose Luis Rivero Date: Thu, 11 Apr 2024 00:21:47 +0200 Subject: [PATCH 10/18] Fix compiler warnings in GCC-13 (Noble) (#616) GCC-13 is complaining about "pointers returned from a mismatched allocation function" in the UNIT_ImageDisplay_TEST. There are 3 occurences where a shared pointer is created from a simple type while the object handled is really a C array. The commit changes the type to indicate that it is in fact an array. Signed-off-by: Jose Luis Rivero --- src/plugins/image_display/ImageDisplay_TEST.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/image_display/ImageDisplay_TEST.cc b/src/plugins/image_display/ImageDisplay_TEST.cc index 4d75636f4..3e7f1082f 100644 --- a/src/plugins/image_display/ImageDisplay_TEST.cc +++ b/src/plugins/image_display/ImageDisplay_TEST.cc @@ -269,7 +269,7 @@ TEST(ImageDisplayTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(ReceiveImage)) // red image int bufferSize = msg.width() * msg.height() * bpp; - std::shared_ptr buffer(new unsigned char[bufferSize]); + std::shared_ptr buffer(new unsigned char[bufferSize]); for (int i = 0; i < bufferSize; i += bpp) { buffer.get()[i] = 255u; @@ -371,7 +371,7 @@ TEST(ImageDisplayTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(ReceiveImageFloat32)) // first half is gray, second half is black int bufferSize = msg.width() * msg.height() * bpp; - std::shared_ptr buffer(new float[bufferSize]); + std::shared_ptr buffer(new float[bufferSize]); for (unsigned int y = 0; y < msg.width(); ++y) { float v = 0.5f * static_cast(y / (msg.height() / 2.0) + 1); @@ -485,7 +485,7 @@ TEST(ImageDisplayTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(ReceiveImageInt16)) // first half is black, second half is white int bufferSize = msg.width() * msg.height() * bpp; - std::shared_ptr buffer(new uint16_t[bufferSize]); + std::shared_ptr buffer(new uint16_t[bufferSize]); for (unsigned int y = 0; y < msg.width(); ++y) { uint16_t v = 100 * static_cast(y / (msg.height() / 2.0) + 1); From ac851e62862a9812a117c2f3913de992003cd7e5 Mon Sep 17 00:00:00 2001 From: "Addisu Z. Taddese" Date: Thu, 11 Apr 2024 10:36:41 -0500 Subject: [PATCH 11/18] Prepare for 8.1.1 Release (#617) Signed-off-by: Addisu Z. Taddese --- CMakeLists.txt | 2 +- Changelog.md | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a8725885..ea53f5dea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(gz-gui8 VERSION 8.1.0) +project(gz-gui8 VERSION 8.1.1) #============================================================================ # Find gz-cmake diff --git a/Changelog.md b/Changelog.md index 33b15219e..5e472daf4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,13 @@ ## Gazebo GUI 8 +### Gazebo GUI 8.1.1 (2024-04-10) + +1. Fix compiler warnings in GCC-13 (Noble) + * [Pull request #616](https://github.com/gazebosim/gz-gui/pull/616) + +1. Use relative install paths for plugin shared libraries and gz-tools data + * [Pull request #614](https://github.com/gazebosim/gz-gui/pull/614) + ### Gazebo GUI 8.1.0 (2024-03-14) 1. Update CI badges in README From b4a0f36487dddbeb572dab810683381e14a45a01 Mon Sep 17 00:00:00 2001 From: "Addisu Z. Taddese" Date: Thu, 25 Apr 2024 17:13:49 -0500 Subject: [PATCH 12/18] Add package.xml (#613) Signed-off-by: Addisu Z. Taddese --- .github/workflows/package_xml.yml | 11 +++++++ package.xml | 53 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 .github/workflows/package_xml.yml create mode 100644 package.xml diff --git a/.github/workflows/package_xml.yml b/.github/workflows/package_xml.yml new file mode 100644 index 000000000..4bd4a9aa0 --- /dev/null +++ b/.github/workflows/package_xml.yml @@ -0,0 +1,11 @@ +name: Validate package.xml + +on: + pull_request: + +jobs: + package-xml: + runs-on: ubuntu-latest + name: Validate package.xml + steps: + - uses: gazebo-tooling/action-gz-ci/validate_package_xml@jammy diff --git a/package.xml b/package.xml new file mode 100644 index 000000000..d94b0e8da --- /dev/null +++ b/package.xml @@ -0,0 +1,53 @@ + + + + gz-gui8 + 8.1.1 + Gazebo GUI : Graphical interfaces for robotics applications + Jenn Nguyen + Apache License 2.0 + https://github.com/gazebosim/gz-rendering + + cmake + + gz-cmake3 + + gz-common5 + gz-math7 + gz-msgs10 + gz-plugin2 + gz-rendering8 + gz-tools2 + gz-transport13 + gz-utils2 + libqt5-core + libqt5-qml + libqt5-quick + libqt5-widgets + protobuf-dev + qml-module-qt-labs-folderlistmodel + qml-module-qt-labs-platform + qml-module-qt-labs-settings + qml-module-qtcharts + qml-module-qtgraphicaleffects + qml-module-qtlocation + qml-module-qtpositioning + qml-module-qtquick-controls2 + qml-module-qtquick-controls + qml-module-qtquick-dialogs + qml-module-qtquick-extras + qml-module-qtquick-layouts + qml-module-qtquick-templates2 + qml-module-qtquick-window2 + qml-module-qtquick2 + qtbase5-dev + qtdeclarative5-dev + qtquickcontrols2-5-dev + tinyxml2 + + xvfb + + + cmake + + From 1a04fbb127e2e7de7df352a2a915a448f5710231 Mon Sep 17 00:00:00 2001 From: Benjamin Perseghetti Date: Wed, 22 May 2024 17:10:10 -0400 Subject: [PATCH 13/18] Enhanced tracking camera and user visualization experience (#619) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Benjamin Perseghetti Co-authored-by: Alejandro Hernández Cordero --- examples/standalone/scene_provider/README.md | 40 +- src/plugins/CMakeLists.txt | 1 + src/plugins/camera_tracking/CameraTracking.cc | 382 +++++++++++++++--- src/plugins/camera_tracking/CameraTracking.hh | 9 +- .../camera_tracking/CameraTracking.qml | 8 +- .../camera_tracking_config/CMakeLists.txt | 6 + .../CameraTrackingConfig.cc | 162 ++++++++ .../CameraTrackingConfig.hh | 72 ++++ .../CameraTrackingConfig.qml | 208 ++++++++++ .../CameraTrackingConfig.qrc | 5 + 10 files changed, 820 insertions(+), 73 deletions(-) create mode 100644 src/plugins/camera_tracking_config/CMakeLists.txt create mode 100644 src/plugins/camera_tracking_config/CameraTrackingConfig.cc create mode 100644 src/plugins/camera_tracking_config/CameraTrackingConfig.hh create mode 100644 src/plugins/camera_tracking_config/CameraTrackingConfig.qml create mode 100644 src/plugins/camera_tracking_config/CameraTrackingConfig.qrc diff --git a/examples/standalone/scene_provider/README.md b/examples/standalone/scene_provider/README.md index 3183a83e4..ce2da00fc 100644 --- a/examples/standalone/scene_provider/README.md +++ b/examples/standalone/scene_provider/README.md @@ -9,7 +9,7 @@ plugin to update the scene using Gazebo Transport. ## Build -``` +```bash cd examples/standalone/scene_provider mkdir build cd build @@ -21,14 +21,14 @@ make In one terminal, start the scene provider: -``` +```bash cd examples/standalone/scene_provider/build ./scene_provider ``` On another terminal, start the example config: -``` +```bash gz gui -c examples/config/scene3d.config ``` @@ -42,24 +42,48 @@ Some commands to test camera tracking with this demo: Move to box: -``` +```bash gz service -s /gui/move_to --reqtype gz.msgs.StringMsg --reptype gz.msgs.Boolean --timeout 2000 --req 'data: "box_model"' ``` Echo camera pose: -``` +```bash gz topic -e -t /gui/camera/pose ``` -Follow box: +Echo camera tracking information: +```bash +gz topic -e -t /gui/currently_tracked ``` -gz service -s /gui/follow --reqtype gz.msgs.StringMsg --reptype gz.msgs.Boolean --timeout 2000 --req 'data: "box_model"' + +Follow box from track topic: + +```bash +gz topic -t /gui/track -m gz.msgs.CameraTrack -p 'track_mode: 2, follow_target: { name: "box_model"}' ``` -Update follow offset: +Follow box from track topic: +```bash +gz topic -t /gui/track -m gz.msgs.CameraTrack -p 'track_mode: 2, follow_target: "box_model", follow_offset: {x: -1, y: 0, z: 1}' ``` + +Update follow offset from track topic: + +```bash +gz topic -t /gui/track -m gz.msgs.CameraTrack -p 'track_mode: 2, follow_target: {name: "box_model"}, follow_offset: {x: -1, y: 0, z: 1}' +``` + +Follow box from service (deprecated): + +```bash +gz service -s /gui/follow --reqtype gz.msgs.StringMsg --reptype gz.msgs.Boolean --timeout 2000 --req 'data: "box_model"' +``` + +Update follow offset from follow offset service (deprecated): + +```bash gz service -s /gui/follow/offset --reqtype gz.msgs.Vector3d --reptype gz.msgs.Boolean --timeout 2000 --req 'x: 5, y: 5, z: 5' ``` diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 01f7fc687..81ca4d848 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -116,6 +116,7 @@ endfunction() # Plugins add_subdirectory(camera_fps) add_subdirectory(camera_tracking) +add_subdirectory(camera_tracking_config) add_subdirectory(grid_config) add_subdirectory(image_display) add_subdirectory(interactive_view_control) diff --git a/src/plugins/camera_tracking/CameraTracking.cc b/src/plugins/camera_tracking/CameraTracking.cc index 172bb6e05..2042459d4 100644 --- a/src/plugins/camera_tracking/CameraTracking.cc +++ b/src/plugins/camera_tracking/CameraTracking.cc @@ -1,5 +1,6 @@ /* * Copyright (C) 2021 Open Source Robotics Foundation + * Copyright (C) 2024 Rudis Laboratories LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +17,13 @@ */ #include +#include #include +#include #include +#include +#include #include #include #include @@ -59,6 +64,10 @@ class CameraTrackingPrivate public: bool OnMoveTo(const msgs::StringMsg &_msg, msgs::Boolean &_res); + /// \brief Callback for a track message + /// \param[in] _msg Message is of type CameraTrack. + public: void OnTrackSub(const msgs::CameraTrack &_msg); + /// \brief Callback for a follow request /// \param[in] _msg Request message to set the target to follow. /// \param[in] _res Response data @@ -96,27 +105,42 @@ class CameraTrackingPrivate //// \brief Pointer to the rendering scene public: rendering::ScenePtr scene = nullptr; + /// \brief Target to track + public: std::string selectedTrackTarget; + /// \brief Target to follow - public: std::string followTarget; + public: std::string selectedFollowTarget; - /// \brief Wait for follow target - public: bool followTargetWait = false; + /// \brief Wait for target to track + public: bool selectedTargetWait = false; /// \brief Offset of camera from target being followed - public: math::Vector3d followOffset = math::Vector3d(-5, 0, 3); + public: math::Vector3d followOffset = math::Vector3d(-3, 0, 2); + + /// \brief Offset on target to be tracked + public: math::Vector3d trackOffset = math::Vector3d(0, 0, 0); - /// \brief Flag to indicate the follow offset needs to be updated - public: bool followOffsetDirty = false; + /// \brief Camera tracking message + public: gz::msgs::CameraTrack trackMsg; - /// \brief Flag to indicate the follow offset has been updated - public: bool newFollowOffset = true; + /// \brief Flag to indicate new tracking + public: bool newTrack = true; + + /// \brief Track P gain + public: double trackPGain = 0.01; /// \brief Follow P gain public: double followPGain = 0.01; - /// \brief True follow the target at an offset that is in world frame, - /// false to follow in target's local frame - public: bool followWorldFrame = false; + /// \brief Free Look P gain + public: double freeLookPGain = 1.0; + + /// \brief Default track mode to None + public: int trackMode = gz::msgs::CameraTrack::NONE; + + /// \brief True track the target at an offset that is in world frame, + /// false to track in target's local frame + public: bool trackWorldFrame = false; /// \brief Last move to animation time public: std::chrono::time_point prevMoveToTime; @@ -136,14 +160,20 @@ class CameraTrackingPrivate /// \brief Move to service public: std::string moveToService; + /// \brief Follow service (deprecated) + public: std::string followService; + + /// \brief Follow offset service (deprecated) + public: std::string followOffsetService; + /// \brief The pose set from the move to pose service. public: std::optional moveToPoseValue; - /// \brief Follow service - public: std::string followService; + /// \brief Track topic + public: std::string trackTopic; - /// \brief Follow offset service - public: std::string followOffsetService; + /// \brief Track status topic + public: std::string trackStatusTopic; /// \brief Camera pose topic public: std::string cameraPoseTopic; @@ -151,6 +181,9 @@ class CameraTrackingPrivate /// \brief Move to pose service public: std::string moveToPoseService; + /// \brief Camera pose publisher + public: transport::Node::Publisher trackStatusPub; + /// \brief Camera pose publisher public: transport::Node::Publisher cameraPosePub; @@ -192,7 +225,21 @@ void CameraTrackingPrivate::Initialize() this->node.Advertise(this->followService, &CameraTrackingPrivate::OnFollow, this); gzmsg << "Follow service on [" - << this->followService << "]" << std::endl; + << this->followService << "] (deprecated)" << std::endl; + + // track + this->trackTopic = "/gui/track"; + this->node.Subscribe(this->trackTopic, + &CameraTrackingPrivate::OnTrackSub, this); + gzmsg << "Tracking topic on [" + << this->trackTopic << "]" << std::endl; + + // tracking status + this->trackStatusTopic = "/gui/currently_tracked"; + this->trackStatusPub = + this->node.Advertise(this->trackStatusTopic); + gzmsg << "Tracking status topic on [" + << this->trackStatusTopic << "]" << std::endl; // move to pose service this->moveToPoseService = @@ -214,7 +261,7 @@ void CameraTrackingPrivate::Initialize() this->node.Advertise(this->followOffsetService, &CameraTrackingPrivate::OnFollowOffset, this); gzmsg << "Follow offset service on [" - << this->followOffsetService << "]" << std::endl; + << this->followOffsetService << "] (deprecated)" << std::endl; } ///////////////////////////////////////////////// @@ -233,12 +280,60 @@ bool CameraTrackingPrivate::OnFollow(const msgs::StringMsg &_msg, msgs::Boolean &_res) { std::lock_guard lock(this->mutex); - this->followTarget = _msg.data(); + this->selectedFollowTarget = _msg.data(); _res.set_data(true); + + this->trackMode = gz::msgs::CameraTrack::FOLLOW; + + this->newTrack = true; return true; } +///////////////////////////////////////////////// +void CameraTrackingPrivate::OnTrackSub(const msgs::CameraTrack &_msg) +{ + std::lock_guard lock(this->mutex); + gzmsg << "Got new track message." << std::endl; + + if (_msg.track_mode() != gz::msgs::CameraTrack::USE_LAST) + { + this->trackMode = _msg.track_mode(); + } + if (!_msg.follow_target().name().empty()) + { + this->selectedFollowTarget = _msg.follow_target().name(); + } + if (!_msg.track_target().name().empty()) + { + this->selectedTrackTarget = _msg.track_target().name(); + } + if (_msg.follow_target().name().empty() && _msg.track_target().name().empty() + && _msg.track_mode() != gz::msgs::CameraTrack::USE_LAST) + { + gzmsg << "Track and Follow target names empty."<< std::endl; + } + if (_msg.has_follow_offset()) + { + this->followOffset = msgs::Convert(_msg.follow_offset()); + } + if (_msg.has_track_offset()) + { + this->trackOffset = msgs::Convert(_msg.track_offset()); + } + if (_msg.track_pgain() > 0.00001) + { + this->trackPGain = _msg.track_pgain(); + } + if (_msg.follow_pgain() > 0.00001) + { + this->followPGain = _msg.follow_pgain(); + } + + this->newTrack = true; + return; +} + ///////////////////////////////////////////////// void CameraTrackingPrivate::OnMoveToComplete() { @@ -256,9 +351,9 @@ bool CameraTrackingPrivate::OnFollowOffset(const msgs::Vector3d &_msg, msgs::Boolean &_res) { std::lock_guard lock(this->mutex); - if (!this->followTarget.empty()) + if (!this->selectedFollowTarget.empty()) { - this->newFollowOffset = true; + this->newTrack = true; this->followOffset = msgs::Convert(_msg); } @@ -364,66 +459,114 @@ void CameraTrackingPrivate::OnRender() } } - // Follow + // Track { - GZ_PROFILE("CameraTrackingPrivate::OnRender Follow"); - // reset follow mode if target node got removed - if (!this->followTarget.empty()) + GZ_PROFILE("CameraTrackingPrivate::OnRender Track"); + // reset track mode if target node got removed + if (!this->selectedFollowTarget.empty()) { - rendering::NodePtr target = this->scene->NodeByName(this->followTarget); - if (!target && !this->followTargetWait) + rendering::NodePtr targetFollow = this->scene->NodeByName( + this->selectedFollowTarget); + if (!targetFollow && !this->selectedTargetWait) { this->camera->SetFollowTarget(nullptr); + this->selectedFollowTarget.clear(); + } + } + if (!this->selectedTrackTarget.empty()) + { + rendering::NodePtr targetTrack = this->scene->NodeByName( + this->selectedTrackTarget); + if (!targetTrack && !this->selectedTargetWait) + { this->camera->SetTrackTarget(nullptr); - this->followTarget.clear(); + this->selectedTrackTarget.clear(); } } if (!this->moveToTarget.empty()) return; - rendering::NodePtr followTargetTmp = this->camera->FollowTarget(); - if (!this->followTarget.empty()) + rendering::NodePtr selectedFollowTargetTmp = this->camera->FollowTarget(); + rendering::NodePtr selectedTrackTargetTmp = this->camera->TrackTarget(); + if (!this->selectedTrackTarget.empty() || + !this->selectedFollowTarget.empty()) { - rendering::NodePtr target = scene->NodeByName( - this->followTarget); - if (target) + rendering::NodePtr targetFollow = this->scene->NodeByName( + this->selectedFollowTarget); + rendering::NodePtr targetTrack = this->scene->NodeByName( + this->selectedTrackTarget); + if (targetFollow || targetTrack) { - if (!followTargetTmp || target != followTargetTmp - || this->newFollowOffset) + if (this->trackMode == gz::msgs::CameraTrack::FOLLOW_FREE_LOOK || + this->trackMode == gz::msgs::CameraTrack::FOLLOW || + this->trackMode == gz::msgs::CameraTrack::FOLLOW_LOOK_AT ) { - this->camera->SetFollowTarget(target, - this->followOffset, - this->followWorldFrame); - this->camera->SetFollowPGain(this->followPGain); - - this->camera->SetTrackTarget(target); - // found target, no need to wait anymore - this->newFollowOffset = false; - this->followTargetWait = false; + if (!selectedFollowTargetTmp || + targetFollow != selectedFollowTargetTmp || + this->newTrack) + { + this->trackWorldFrame = false; + this->camera->SetFollowTarget(targetFollow, + this->followOffset, + this->trackWorldFrame); + if (this->trackMode == gz::msgs::CameraTrack::FOLLOW) + { + this->camera->SetTrackTarget(targetFollow); + this->camera->SetTrackPGain(this->followPGain); + this->camera->SetFollowPGain(this->trackPGain); + } + if (this->trackMode == gz::msgs::CameraTrack::FOLLOW_LOOK_AT) + { + this->camera->SetTrackTarget(targetTrack); + this->camera->SetTrackPGain(this->followPGain); + this->camera->SetFollowPGain(this->trackPGain); + } + if (this->trackMode == gz::msgs::CameraTrack::FOLLOW_FREE_LOOK) + { + this->camera->SetTrackTarget(nullptr); + this->camera->SetFollowPGain(this->freeLookPGain); + } + this->newTrack = false; + this->selectedTargetWait = false; + } } - else if (this->followOffsetDirty) + if (this->trackMode == gz::msgs::CameraTrack::TRACK) { - math::Vector3d offset = - this->camera->WorldPosition() - target->WorldPosition(); - if (!this->followWorldFrame) + if (!selectedTrackTargetTmp || + targetTrack != selectedTrackTargetTmp || + this->newTrack) { - offset = target->WorldRotation().RotateVectorReverse(offset); + this->trackWorldFrame = true; + this->camera->SetFollowTarget(nullptr); + this->camera->SetTrackTarget(targetTrack, + this->trackOffset, + this->trackWorldFrame); + this->camera->SetTrackPGain(this->trackPGain); + this->newTrack = false; + this->selectedTargetWait = false; } - this->camera->SetFollowOffset(offset); - this->followOffsetDirty = false; } } - else if (!this->followTargetWait) + else if (!this->selectedTargetWait) { + gzerr << "Unable to track target. Target: '" + << this->selectedTrackTarget << "' not found" << std::endl; gzerr << "Unable to follow target. Target: '" - << this->followTarget << "' not found" << std::endl; - this->followTarget.clear(); + << this->selectedFollowTarget << "' not found" << std::endl; + this->selectedFollowTarget.clear(); + this->selectedTrackTarget.clear(); } } - else if (followTargetTmp) + else { - this->camera->SetFollowTarget(nullptr); - this->camera->SetTrackTarget(nullptr); + if (selectedFollowTargetTmp) + { + this->camera->SetFollowTarget(nullptr); + } + if (selectedTrackTargetTmp) + { + this->camera->SetTrackTarget(nullptr); + } } } } @@ -443,6 +586,96 @@ CameraTracking::CameraTracking() auto poseMsg = msgs::Convert(this->dataPtr->camera->WorldPose()); this->dataPtr->cameraPosePub.Publish(poseMsg); } + if (this->dataPtr->trackStatusPub.HasConnections()) + { + if (this->dataPtr->trackMode == gz::msgs::CameraTrack::TRACK) + { + this->dataPtr->trackMsg.set_track_mode(gz::msgs::CameraTrack::TRACK); + this->dataPtr->trackMsg.mutable_track_target()->set_name( + this->dataPtr->selectedTrackTarget); + this->dataPtr->trackMsg.mutable_track_offset()->set_x( + this->dataPtr->trackOffset.X()); + this->dataPtr->trackMsg.mutable_track_offset()->set_y( + this->dataPtr->trackOffset.Y()); + this->dataPtr->trackMsg.mutable_track_offset()->set_z( + this->dataPtr->trackOffset.Z()); + this->dataPtr->trackMsg.set_track_pgain( + this->dataPtr->trackPGain); + this->dataPtr->trackMsg.clear_follow_target(); + this->dataPtr->trackMsg.clear_follow_offset(); + this->dataPtr->trackMsg.clear_follow_pgain(); + } + else if (this->dataPtr->trackMode == gz::msgs::CameraTrack::FOLLOW) + { + this->dataPtr->trackMsg.set_track_mode(gz::msgs::CameraTrack::FOLLOW); + this->dataPtr->trackMsg.mutable_follow_target()->set_name( + this->dataPtr->selectedFollowTarget); + this->dataPtr->trackMsg.mutable_follow_offset()->set_x( + this->dataPtr->followOffset.X()); + this->dataPtr->trackMsg.mutable_follow_offset()->set_y( + this->dataPtr->followOffset.Y()); + this->dataPtr->trackMsg.mutable_follow_offset()->set_z( + this->dataPtr->followOffset.Z()); + this->dataPtr->trackMsg.set_follow_pgain(this->dataPtr->followPGain); + this->dataPtr->trackMsg.clear_track_target(); + this->dataPtr->trackMsg.clear_track_offset(); + this->dataPtr->trackMsg.clear_track_pgain(); + } + else if (this->dataPtr->trackMode == + gz::msgs::CameraTrack::FOLLOW_FREE_LOOK) + { + this->dataPtr->trackMsg.set_track_mode( + gz::msgs::CameraTrack::FOLLOW_FREE_LOOK); + this->dataPtr->trackMsg.mutable_follow_target()->set_name( + this->dataPtr->selectedFollowTarget); + this->dataPtr->trackMsg.mutable_follow_offset()->set_x( + this->dataPtr->followOffset.X()); + this->dataPtr->trackMsg.mutable_follow_offset()->set_y( + this->dataPtr->followOffset.Y()); + this->dataPtr->trackMsg.mutable_follow_offset()->set_z( + this->dataPtr->followOffset.Z()); + this->dataPtr->trackMsg.set_follow_pgain(this->dataPtr->followPGain); + this->dataPtr->trackMsg.clear_track_target(); + this->dataPtr->trackMsg.clear_track_offset(); + this->dataPtr->trackMsg.clear_track_pgain(); + } + else if (this->dataPtr->trackMode == + gz::msgs::CameraTrack::FOLLOW_LOOK_AT) + { + this->dataPtr->trackMsg.set_track_mode( + gz::msgs::CameraTrack::FOLLOW_LOOK_AT); + this->dataPtr->trackMsg.mutable_follow_target()->set_name( + this->dataPtr->selectedFollowTarget); + this->dataPtr->trackMsg.mutable_track_target()->set_name( + this->dataPtr->selectedTrackTarget); + this->dataPtr->trackMsg.mutable_follow_offset()->set_x( + this->dataPtr->followOffset.X()); + this->dataPtr->trackMsg.mutable_follow_offset()->set_y( + this->dataPtr->followOffset.Y()); + this->dataPtr->trackMsg.mutable_follow_offset()->set_z( + this->dataPtr->followOffset.Z()); + this->dataPtr->trackMsg.mutable_track_offset()->set_x( + this->dataPtr->trackOffset.X()); + this->dataPtr->trackMsg.mutable_track_offset()->set_y( + this->dataPtr->trackOffset.Y()); + this->dataPtr->trackMsg.mutable_track_offset()->set_z( + this->dataPtr->trackOffset.Z()); + this->dataPtr->trackMsg.set_follow_pgain(this->dataPtr->followPGain); + this->dataPtr->trackMsg.set_track_pgain(this->dataPtr->trackPGain); + } + else + { + this->dataPtr->trackMsg.set_track_mode(gz::msgs::CameraTrack::NONE); + this->dataPtr->trackMsg.clear_track_target(); + this->dataPtr->trackMsg.clear_track_offset(); + this->dataPtr->trackMsg.clear_track_pgain(); + this->dataPtr->trackMsg.clear_follow_target(); + this->dataPtr->trackMsg.clear_follow_offset(); + this->dataPtr->trackMsg.clear_follow_pgain(); + } + + this->dataPtr->trackStatusPub.Publish(this->dataPtr->trackMsg); + } }); this->dataPtr->timer->setInterval(1000.0 / 50.0); this->dataPtr->timer->start(); @@ -452,11 +685,39 @@ CameraTracking::CameraTracking() CameraTracking::~CameraTracking() = default; ///////////////////////////////////////////////// -void CameraTracking::LoadConfig(const tinyxml2::XMLElement *) +void CameraTracking::LoadConfig(const tinyxml2::XMLElement *_pluginElem) { if (this->title.empty()) this->title = "Camera tracking"; + if (_pluginElem) + { + if (auto followTargetElem = _pluginElem->FirstChildElement("follow_target")) + { + this->dataPtr->selectedFollowTarget = followTargetElem->GetText(); + gzmsg << "CameraTracking: Loaded follow target from sdf [" + << this->dataPtr->selectedFollowTarget << "]" << std::endl; + this->dataPtr->selectedTargetWait = true; + } + if (auto followOffsetElem = _pluginElem->FirstChildElement("follow_offset")) + { + std::stringstream followOffsetStr; + followOffsetStr << std::string(followOffsetElem->GetText()); + followOffsetStr >> this->dataPtr->followOffset; + gzmsg << "CameraTracking: Loaded offset from sdf [" + << this->dataPtr->followOffset << "]" << std::endl; + this->dataPtr->newTrack = true; + } + if (auto followPGainElem = _pluginElem->FirstChildElement("follow_pgain")) + { + this->dataPtr->followPGain = std::stod( + std::string(followPGainElem->GetText())); + gzmsg << "CameraTracking: Loaded follow pgain from sdf [" + << this->dataPtr->followPGain << "]" << std::endl; + this->dataPtr->newTrack = true; + } + } + App()->findChild()->installEventFilter(this); } @@ -465,9 +726,12 @@ void CameraTrackingPrivate::HandleKeyRelease(events::KeyReleaseOnScene *_e) { if (_e->Key().Key() == Qt::Key_Escape) { - if (!this->followTarget.empty()) + this->trackMode = gz::msgs::CameraTrack::NONE; + if (!this->selectedFollowTarget.empty() || + !this->selectedTrackTarget.empty()) { - this->followTarget = std::string(); + this->selectedFollowTarget = std::string(); + this->selectedTrackTarget = std::string(); _e->accept(); } diff --git a/src/plugins/camera_tracking/CameraTracking.hh b/src/plugins/camera_tracking/CameraTracking.hh index 68176e2c5..ae6833b9c 100644 --- a/src/plugins/camera_tracking/CameraTracking.hh +++ b/src/plugins/camera_tracking/CameraTracking.hh @@ -1,5 +1,6 @@ /* * Copyright (C) 2021 Open Source Robotics Foundation + * Copyright (C) 2024 Rudis Laboratories LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,12 +31,14 @@ namespace gz::gui::plugins /// and "follow". /// /// Services: + /// * `/gui/follow`: Set the user camera to follow a given target, + /// identified by name (deprecated). + /// * `/gui/follow/offset`: Set the offset for following (deprecated). /// * `/gui/move_to`: Move the user camera to look at a given target, /// identified by name. /// * `/gui/move_to/pose`: Move the user camera to a given pose. - /// * `/gui/follow`: Set the user camera to follow a given target, - /// identified by name. - /// * `/gui/follow/offset`: Set the offset for following. + /// * `/gui/track`: Set the user camera to follow a given target, + /// identified by name, offset, pgain, track type. /// /// Topics: /// * `/gui/camera/pose`: Publishes the current user camera pose. diff --git a/src/plugins/camera_tracking/CameraTracking.qml b/src/plugins/camera_tracking/CameraTracking.qml index 09c339f0b..a8c82d45e 100644 --- a/src/plugins/camera_tracking/CameraTracking.qml +++ b/src/plugins/camera_tracking/CameraTracking.qml @@ -1,5 +1,6 @@ /* * Copyright (C) 2021 Open Source Robotics Foundation + * Copyright (C) 2024 Rudis Laboratories LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,11 +27,12 @@ ColumnLayout { anchors.margins: 10 property string message: 'Services provided:
    ' + + '
  • /gui/follow/pose
  • ' + '
  • /gui/move_to
  • ' + '
  • /gui/move_to/pose
  • ' + - '
  • /gui/follow
  • ' + - '
  • /gui/follow/offset

Topics provided:
    ' + - '
  • /gui/camera/pose
' + '
  • /gui/track

  • Topics provided:
      ' + + '
    • /gui/camera/pose
    • '+ + '
    • /gui/currently_tracked
    ' Label { Layout.fillWidth: true diff --git a/src/plugins/camera_tracking_config/CMakeLists.txt b/src/plugins/camera_tracking_config/CMakeLists.txt new file mode 100644 index 000000000..b6877357c --- /dev/null +++ b/src/plugins/camera_tracking_config/CMakeLists.txt @@ -0,0 +1,6 @@ +gz_gui_add_plugin(CameraTrackingConfig + SOURCES + CameraTrackingConfig.cc + QT_HEADERS + CameraTrackingConfig.hh +) diff --git a/src/plugins/camera_tracking_config/CameraTrackingConfig.cc b/src/plugins/camera_tracking_config/CameraTrackingConfig.cc new file mode 100644 index 000000000..c61f8ac44 --- /dev/null +++ b/src/plugins/camera_tracking_config/CameraTrackingConfig.cc @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2024 CogniPilot Foundation + * Copyright (C) 2024 Rudis Laboratories LLC + * + * 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 +#include +#include +#include + +#include "gz/gui/Application.hh" +#include "gz/gui/Conversions.hh" +#include "gz/gui/GuiEvents.hh" +#include "gz/gui/MainWindow.hh" + +#include + +#include "CameraTrackingConfig.hh" + +/// \brief Private data class for CameraTrackingConfig +class gz::gui::plugins::CameraTrackingConfigPrivate +{ + + /// \brief Topic for track message + public: std::string cameraTrackingTopic; + + /// \brief tracking offset + public: math::Vector3d trackOffset{math::Vector3d(0.0, 0.0, 0.0)}; + + /// \brief track P gain + public: double trackPGain{0.01}; + + /// \brief Offset of camera from target being followed + public: math::Vector3d followOffset{math::Vector3d(-3.0, 0.0, -2.0)}; + + /// \brief Follow P gain + public: double followPGain{0.01}; + + public: transport::Node node; + + /// \brief Process updated track + public: void UpdateTracking(); + + /// \brief flag for updating + public: bool newTrackingUpdate = false; + + /// \brief track publisher + public: transport::Node::Publisher trackingPub; +}; + +using namespace gz; +using namespace gui; +using namespace plugins; + +///////////////////////////////////////////////// +CameraTrackingConfig::CameraTrackingConfig() + : gz::gui::Plugin(), dataPtr(std::make_unique()) +{ +} + +///////////////////////////////////////////////// +CameraTrackingConfig::~CameraTrackingConfig() = default; + +///////////////////////////////////////////////// +void CameraTrackingConfig::LoadConfig(const tinyxml2::XMLElement *) +{ + if (this->title.empty()) + this->title = "Camera Tracking Config"; + + // Track target pose service + this->dataPtr->cameraTrackingTopic = "/gui/track"; + this->dataPtr->trackingPub = + this->dataPtr->node.Advertise( + this->dataPtr->cameraTrackingTopic); + gzmsg << "CameraTrackingConfig: Tracking topic publisher advertised on [" + << this->dataPtr->cameraTrackingTopic << "]" << std::endl; + + gui::App()->findChild< + MainWindow *>()->installEventFilter(this); +} + +///////////////////////////////////////////////// +bool CameraTrackingConfig::eventFilter(QObject *_obj, QEvent *_event) +{ + if (_event->type() == events::Render::kType) + { + if (this->dataPtr->newTrackingUpdate) + { + this->dataPtr->UpdateTracking(); + } + } + + // Standard event processing + return QObject::eventFilter(_obj, _event); +} + +///////////////////////////////////////////////// +void CameraTrackingConfig::SetTracking( + double _tx, double _ty, double _tz, double _tp, + double _fx, double _fy, double _fz, double _fp) +{ + if (!this->dataPtr->newTrackingUpdate) + { + this->dataPtr->trackOffset = math::Vector3d( + _tx, _ty, _tz); + this->dataPtr->followOffset = math::Vector3d( + _fx, _fy, _fz); + this->dataPtr->trackPGain = _tp; + this->dataPtr->followPGain = _fp; + gzmsg << "CameraTrackingConfig: Track: Offset(" + << this->dataPtr->trackOffset << "), PGain(" + << this->dataPtr->trackPGain << ")" << std::endl; + gzmsg << "CameraTrackingConfig: Follow: Offset(" + << this->dataPtr->followOffset << "), PGain(" + << this->dataPtr->followPGain << ")" << std::endl; + this->dataPtr->newTrackingUpdate = true; + } +} + +///////////////////////////////////////////////// +void CameraTrackingConfigPrivate::UpdateTracking() +{ + // Track + msgs::CameraTrack trackingMsg; + trackingMsg.set_track_mode(msgs::CameraTrack::USE_LAST); + trackingMsg.mutable_track_offset()->set_x(this->trackOffset.X()); + trackingMsg.mutable_track_offset()->set_y(this->trackOffset.Y()); + trackingMsg.mutable_track_offset()->set_z(this->trackOffset.Z()); + trackingMsg.mutable_follow_offset()->set_x(this->followOffset.X()); + trackingMsg.mutable_follow_offset()->set_y(this->followOffset.Y()); + trackingMsg.mutable_follow_offset()->set_z(this->followOffset.Z()); + trackingMsg.set_follow_pgain(this->followPGain); + trackingMsg.set_track_pgain(this->trackPGain); + + this->trackingPub.Publish(trackingMsg); + gzmsg << "CameraTrackingConfig: Publishing message." << std::endl; + this->newTrackingUpdate = false; +} + +// Register this plugin +GZ_ADD_PLUGIN(CameraTrackingConfig, + gui::Plugin) diff --git a/src/plugins/camera_tracking_config/CameraTrackingConfig.hh b/src/plugins/camera_tracking_config/CameraTrackingConfig.hh new file mode 100644 index 000000000..dca58a52e --- /dev/null +++ b/src/plugins/camera_tracking_config/CameraTrackingConfig.hh @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2024 CogniPilot Foundation + * Copyright (C) 2024 Rudis Laboratories LLC + * + * 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_CAMERATRACKINGCONFIG_HH_ +#define GZ_GUI_PLUGINS_CAMERATRACKINGCONFIG_HH_ + +#include +#include +#include + +#include "gz/gui/Plugin.hh" + +namespace gz +{ +namespace gui +{ +namespace plugins +{ + class CameraTrackingConfigPrivate; + + class CameraTrackingConfig : public Plugin + { + Q_OBJECT + + /// \brief Constructor + public: CameraTrackingConfig(); + + /// \brief Destructor + public: virtual ~CameraTrackingConfig(); + + // Documentation inherited + public: virtual void LoadConfig(const tinyxml2::XMLElement *) + override; + + /// \brief Set the tracking camera, requested from the GUI. + /// \param[in] _tx The track offset in x + /// \param[in] _ty The track offset in y + /// \param[in] _tz The track offset in z + /// \param[in] _tp The track camera P gain + /// \param[in] _fx The follow offset in x + /// \param[in] _fy The follow offset in y + /// \param[in] _fz The follow offset in z + /// \param[in] _fp The follow camera P gain + public slots: void SetTracking( + double _tx, double _ty, double _tz, double _tp, + double _fx, double _fy, double _fz, double _fp); + + // 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_tracking_config/CameraTrackingConfig.qml b/src/plugins/camera_tracking_config/CameraTrackingConfig.qml new file mode 100644 index 000000000..91c5e144a --- /dev/null +++ b/src/plugins/camera_tracking_config/CameraTrackingConfig.qml @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2024 CogniPilot Foundation + * Copyright (C) 2024 Rudis Laboratories LLC + * + * 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.Controls.Material 2.1 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import gz.gui 1.0 + +ColumnLayout { + Layout.minimumWidth: 200 + Layout.minimumHeight: 200 + Layout.margins: 2 + anchors.fill: parent + focus: true + + // X track camera pose + property double xTrackPose: 0.0 + // Y track camera pose + property double yTrackPose: 0.0 + // Z track camera pose + property double zTrackPose: 0.0 + // P Gain track camera pose + property double pGainTrack: 0.01 + // X camera follow distance + property double xFollowOffset: -3.0 + // Y camera follow distance + property double yFollowOffset: 0.0 + // Z camera follow distance + property double zFollowOffset: 2.0 + // P Gain camera follow distance + property double pGainFollow: 0.01 + + GridLayout { + Layout.fillWidth: true + Layout.margins: 2 + columns: 2 + + // X Track Offset + Label { + id: xTrackPoseLabel + text: "Track Offset X (m)" + color: "dimgrey" + } + GzSpinBox { + id: xTrackPoseField + Layout.fillWidth: true + value: xTrackPose + maximumValue: 1000.0 + minimumValue: -1000.0 + decimals: 2 + stepSize: 0.5 + onEditingFinished:{ + xTrackPose = value + CameraTrackingConfig.SetTracking(xTrackPose, yTrackPose, zTrackPose, pGainTrack, xFollowOffset, yFollowOffset, zFollowOffset, pGainFollow) + } + } + // Y Track Offset + Label { + id: yTrackPoseLabel + text: "Track Offset Y (m)" + color: "dimgrey" + } + GzSpinBox { + id: yTrackPoseField + Layout.fillWidth: true + value: yTrackPose + maximumValue: 1000.0 + minimumValue: -1000.0 + decimals: 2 + stepSize: 0.5 + onEditingFinished:{ + yTrackPose = value + CameraTrackingConfig.SetTracking(xTrackPose, yTrackPose, zTrackPose, pGainTrack, xFollowOffset, yFollowOffset, zFollowOffset, pGainFollow) + } + } + // Z Track Offset + Label { + id: zTrackPoseLabel + text: "Track Offset Z (m)" + color: "dimgrey" + } + GzSpinBox { + id: zTrackPoseField + Layout.fillWidth: true + value: zTrackPose + maximumValue: 1000.0 + minimumValue: -1000.0 + decimals: 2 + stepSize: 0.5 + onEditingFinished:{ + zTrackPose = value + CameraTrackingConfig.SetTracking(xTrackPose, yTrackPose, zTrackPose, pGainTrack, xFollowOffset, yFollowOffset, zFollowOffset, pGainFollow) + } + } + // P Gain track + Label { + id: pGainTrackLabel + text: "Track P Gain" + color: "dimgrey" + } + GzSpinBox { + id: pGainTrackField + Layout.fillWidth: true + value: pGainTrack + maximumValue: 1.0 + minimumValue: 0.001 + decimals: 3 + stepSize: 0.01 + onEditingFinished:{ + pGainTrack = value + CameraTrackingConfig.SetTracking(xTrackPose, yTrackPose, zTrackPose, pGainTrack, xFollowOffset, yFollowOffset, zFollowOffset, pGainFollow) + } + } + // X Follow Offset + Label { + id: xFollowOffsetLabel + text: "Follow Offset X (m)" + color: "dimgrey" + } + GzSpinBox { + id: xFollowOffsetField + Layout.fillWidth: true + value: xFollowOffset + maximumValue: 100.0 + minimumValue: -100.0 + decimals: 2 + stepSize: 0.5 + onEditingFinished:{ + xFollowOffset = value + CameraTrackingConfig.SetTracking(xTrackPose, yTrackPose, zTrackPose, pGainTrack, xFollowOffset, yFollowOffset, zFollowOffset,pGainFollow) + } + } + // Y Follow Offset + Label { + id: yFollowOffsetLabel + text: "Follow Offset Y (m)" + color: "dimgrey" + } + GzSpinBox { + id: yFollowOffsetField + Layout.fillWidth: true + value: yFollowOffset + maximumValue: 100.0 + minimumValue: -100.0 + decimals: 2 + stepSize: 0.5 + onEditingFinished:{ + yFollowOffset = value + CameraTrackingConfig.SetTracking(xTrackPose, yTrackPose, zTrackPose, pGainTrack, xFollowOffset, yFollowOffset, zFollowOffset,pGainFollow) + } + } + // Z Follow Offset + Label { + id: zFollowOffsetLabel + text: "Follow Offset Z (m)" + color: "dimgrey" + } + GzSpinBox { + id: zFollowOffsetField + Layout.fillWidth: true + value: zFollowOffset + maximumValue: 100.0 + minimumValue: -100.0 + decimals: 2 + stepSize: 0.5 + onEditingFinished:{ + zFollowOffset = value + CameraTrackingConfig.SetTracking(xTrackPose, yTrackPose, zTrackPose, pGainTrack, xFollowOffset, yFollowOffset, zFollowOffset,pGainFollow) + } + } + // P Gain follow + Label { + id: pGainFollowLabel + text: "Follow Offset P Gain" + color: "dimgrey" + } + GzSpinBox { + id: pGainFollowField + Layout.fillWidth: true + value: pGainFollow + maximumValue: 1.0 + minimumValue: 0.001 + decimals: 3 + stepSize: 0.01 + onEditingFinished:{ + pGainFollow = value + CameraTrackingConfig.SetTracking(xTrackPose, yTrackPose, zTrackPose, pGainTrack, xFollowOffset, yFollowOffset, zFollowOffset,pGainFollow) + } + } + } +} diff --git a/src/plugins/camera_tracking_config/CameraTrackingConfig.qrc b/src/plugins/camera_tracking_config/CameraTrackingConfig.qrc new file mode 100644 index 000000000..5b9e0d08d --- /dev/null +++ b/src/plugins/camera_tracking_config/CameraTrackingConfig.qrc @@ -0,0 +1,5 @@ + + + CameraTrackingConfig.qml + + From 4075ac1b51e3b9d7824c5a58fc04e1f6ad3df6bd Mon Sep 17 00:00:00 2001 From: "Addisu Z. Taddese" Date: Fri, 14 Jun 2024 18:06:42 -0500 Subject: [PATCH 14/18] Prepare for 8.2.0 Release (#624) Signed-off-by: Addisu Z. Taddese --- CMakeLists.txt | 2 +- Changelog.md | 8 ++++++++ package.xml | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea53f5dea..53923ec09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(gz-gui8 VERSION 8.1.1) +project(gz-gui8 VERSION 8.2.0) #============================================================================ # Find gz-cmake diff --git a/Changelog.md b/Changelog.md index 5e472daf4..a6677de3e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,13 @@ ## Gazebo GUI 8 +### Gazebo GUI 8.2.0 (2024-06-14) + +1. Enhanced tracking camera and user visualization experience + * [Pull request #619](https://github.com/gazebosim/gz-gui/pull/619) + +1. Add package.xml + * [Pull request #613](https://github.com/gazebosim/gz-gui/pull/613) + ### Gazebo GUI 8.1.1 (2024-04-10) 1. Fix compiler warnings in GCC-13 (Noble) diff --git a/package.xml b/package.xml index d94b0e8da..8b6cd029c 100644 --- a/package.xml +++ b/package.xml @@ -2,7 +2,7 @@ gz-gui8 - 8.1.1 + 8.2.0 Gazebo GUI : Graphical interfaces for robotics applications Jenn Nguyen Apache License 2.0 From 92f9d783e002c9aed55f60b0a634fe4e69ade964 Mon Sep 17 00:00:00 2001 From: Benjamin Perseghetti Date: Mon, 17 Jun 2024 19:13:41 -0400 Subject: [PATCH 15/18] Backport: Adding cone primitives. (#621) Signed-off-by: Benjamin Perseghetti --- src/plugins/marker_manager/MarkerManager.cc | 2 ++ .../transport_scene_manager/TransportSceneManager.cc | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/plugins/marker_manager/MarkerManager.cc b/src/plugins/marker_manager/MarkerManager.cc index c78d5d990..42db173a8 100644 --- a/src/plugins/marker_manager/MarkerManager.cc +++ b/src/plugins/marker_manager/MarkerManager.cc @@ -610,6 +610,8 @@ gz::rendering::MarkerType MarkerManagerPrivate::MsgToType( return gz::rendering::MarkerType::MT_BOX; case gz::msgs::Marker::CAPSULE: return gz::rendering::MarkerType::MT_CAPSULE; + case gz::msgs::Marker::CONE: + return gz::rendering::MarkerType::MT_CONE; case gz::msgs::Marker::CYLINDER: return gz::rendering::MarkerType::MT_CYLINDER; case gz::msgs::Marker::LINE_STRIP: diff --git a/src/plugins/transport_scene_manager/TransportSceneManager.cc b/src/plugins/transport_scene_manager/TransportSceneManager.cc index 735ed5ee8..a38de6b0f 100644 --- a/src/plugins/transport_scene_manager/TransportSceneManager.cc +++ b/src/plugins/transport_scene_manager/TransportSceneManager.cc @@ -687,6 +687,13 @@ rendering::GeometryPtr TransportSceneManagerPrivate::LoadGeometry( if (_msg.box().has_size()) scale = msgs::Convert(_msg.box().size()); } + else if (_msg.has_cone()) + { + geom = this->scene->CreateCone(); + scale.X() = _msg.cone().radius() * 2; + scale.Y() = scale.X(); + scale.Z() = _msg.cone().length(); + } else if (_msg.has_cylinder()) { geom = this->scene->CreateCylinder(); From 036df090d5fb9323617ad186156e295a85e38421 Mon Sep 17 00:00:00 2001 From: Benjamin Perseghetti Date: Thu, 20 Jun 2024 21:14:32 -0400 Subject: [PATCH 16/18] Prepare for 8.3.0 (#625) Signed-off-by: Benjamin Perseghetti --- CMakeLists.txt | 2 +- Changelog.md | 5 +++++ package.xml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53923ec09..031c72c48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(gz-gui8 VERSION 8.2.0) +project(gz-gui8 VERSION 8.3.0) #============================================================================ # Find gz-cmake diff --git a/Changelog.md b/Changelog.md index a6677de3e..fa89dd6df 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,10 @@ ## Gazebo GUI 8 +### Gazebo GUI 8.3.0 (2024-06-20) + +1. Backport: Adding cone primitives. + * [Pull request #621](https://github.com/gazebosim/gz-gui/pull/621) + ### Gazebo GUI 8.2.0 (2024-06-14) 1. Enhanced tracking camera and user visualization experience diff --git a/package.xml b/package.xml index 8b6cd029c..9efa6d7b5 100644 --- a/package.xml +++ b/package.xml @@ -2,7 +2,7 @@ gz-gui8 - 8.2.0 + 8.3.0 Gazebo GUI : Graphical interfaces for robotics applications Jenn Nguyen Apache License 2.0 From 179f0e659f8cf03edcfe9d445d59875a8a16c3e8 Mon Sep 17 00:00:00 2001 From: Vincent <46542431+VincidaB@users.noreply.github.com> Date: Fri, 19 Jul 2024 13:25:51 -0500 Subject: [PATCH 17/18] Added dark mode for drawer and menu buttons (#626) Signed-off-by: Vincent Belpois --- include/gz/gui/qml/Main.qml | 6 +++--- include/gz/gui/qml/images/drawer_dark.png | Bin 0 -> 7073 bytes include/gz/gui/qml/images/menu_dark.png | Bin 0 -> 5340 bytes include/gz/gui/resources.qrc | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 include/gz/gui/qml/images/drawer_dark.png create mode 100644 include/gz/gui/qml/images/menu_dark.png diff --git a/include/gz/gui/qml/Main.qml b/include/gz/gui/qml/Main.qml index c18154f29..c7e540200 100644 --- a/include/gz/gui/qml/Main.qml +++ b/include/gz/gui/qml/Main.qml @@ -189,8 +189,8 @@ ApplicationWindow contentItem: Image { fillMode: Image.Pad horizontalAlignment: Image.AlignHCenter - verticalAlignment: Image.AlignVCenter - source: "images/drawer.png" + verticalAlignment: Image.AlignVCenter + source: Material.theme === Material.Light ? "images/drawer.png" : "images/drawer_dark.png" } onClicked: drawer.open() } @@ -221,7 +221,7 @@ ApplicationWindow fillMode: Image.Pad horizontalAlignment: Image.AlignHCenter verticalAlignment: Image.AlignVCenter - source: "images/menu.png" + source: Material.theme === Material.Light ? "images/menu.png" : "images/menu_dark.png" } onClicked: pluginMenu.open() diff --git a/include/gz/gui/qml/images/drawer_dark.png b/include/gz/gui/qml/images/drawer_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..7e0089474ad3788a427b6c9c04eabcb14b10dca6 GIT binary patch literal 7073 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 G{C@yF6lf#> literal 0 HcmV?d00001 diff --git a/include/gz/gui/qml/images/menu_dark.png b/include/gz/gui/qml/images/menu_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6f4ad6eb9b1550684329566f9c3b06b1c833a5cd GIT binary patch literal 5340 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 Xz}jqW+*9m2wR3>U@OMA5BqHTM`SBcJ literal 0 HcmV?d00001 diff --git a/include/gz/gui/resources.qrc b/include/gz/gui/resources.qrc index 8a18a99f6..1668662ab 100644 --- a/include/gz/gui/resources.qrc +++ b/include/gz/gui/resources.qrc @@ -24,7 +24,9 @@ qml/images/gazebo_logo.png qml/images/drawer.png + qml/images/drawer_dark.png qml/images/menu.png + qml/images/menu_dark.png qml/images/export_icon.png qml/images/search.svg qml/images/plottable_icon.svg From b26f652e55ba754e587920cf6442cbc739825bc0 Mon Sep 17 00:00:00 2001 From: "Addisu Z. Taddese" Date: Wed, 31 Jul 2024 09:55:45 -0500 Subject: [PATCH 18/18] Fix color distortion in low light conditions (#630) Replaces the gamma correction QML element and instead tells Qt to copy the texture as is without decoding from srgb->rgb. --------- Signed-off-by: Addisu Z. Taddese --- src/plugins/minimal_scene/EngineToQtInterface.cc | 8 +++++++- src/plugins/minimal_scene/MinimalScene.cc | 6 ------ src/plugins/minimal_scene/MinimalScene.qml | 15 --------------- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/plugins/minimal_scene/EngineToQtInterface.cc b/src/plugins/minimal_scene/EngineToQtInterface.cc index 8e82576ff..380f881f4 100644 --- a/src/plugins/minimal_scene/EngineToQtInterface.cc +++ b/src/plugins/minimal_scene/EngineToQtInterface.cc @@ -136,7 +136,13 @@ GLuint EngineToQtInterface::TextureId(gz::rendering::CameraPtr &_camera) { if (!this->NeedsFallback(_camera)) { - return _camera->RenderTextureGLId(); + auto textureId = _camera->RenderTextureGLId(); + + QOpenGLFunctions *glFuncs = this->dataPtr->glContext->functions(); + glFuncs->glBindTexture(GL_TEXTURE_2D, textureId); + glFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, + GL_SKIP_DECODE_EXT); + return textureId; } else { diff --git a/src/plugins/minimal_scene/MinimalScene.cc b/src/plugins/minimal_scene/MinimalScene.cc index 556ea8e10..2a7fb7bd9 100644 --- a/src/plugins/minimal_scene/MinimalScene.cc +++ b/src/plugins/minimal_scene/MinimalScene.cc @@ -1545,12 +1545,6 @@ void MinimalScene::LoadConfig(const tinyxml2::XMLElement *_pluginElem) } renderWindow->SetEngineName(cmdRenderEngine); - // there is a problem with displaying ogre2 render textures that are in - // sRGB format. Workaround for now is to apply gamma correction - // manually. - // There maybe a better way to solve the problem by making OpenGL calls. - if (cmdRenderEngine == std::string("ogre2")) - this->PluginItem()->setProperty("gammaCorrect", true); } ///////////////////////////////////////////////// diff --git a/src/plugins/minimal_scene/MinimalScene.qml b/src/plugins/minimal_scene/MinimalScene.qml index 5969a31c6..62919ec79 100644 --- a/src/plugins/minimal_scene/MinimalScene.qml +++ b/src/plugins/minimal_scene/MinimalScene.qml @@ -25,11 +25,6 @@ Rectangle { Layout.minimumHeight: 200 anchors.fill: parent - /** - * True to enable gamma correction - */ - property bool gammaCorrect: false - /** * Get mouse position on 3D widget */ @@ -54,16 +49,6 @@ Rectangle { visible: MinimalScene.loadingError.length == 0 } - /* - * Gamma correction for sRGB output. Enabled when engine is set to ogre2 - */ - GammaAdjust { - anchors.fill: renderWindow - source: renderWindow - gamma: 2.4 - enabled: gammaCorrect - visible: gammaCorrect - } onParentChanged: { if (undefined === parent)