diff --git a/rqt_image_overlay/CMakeLists.txt b/rqt_image_overlay/CMakeLists.txt
index 9639bc8..9ca7c70 100644
--- a/rqt_image_overlay/CMakeLists.txt
+++ b/rqt_image_overlay/CMakeLists.txt
@@ -36,7 +36,7 @@ qt5_wrap_cpp(SOURCES # Must do this for qt's Meta-Object Compiler.
src/image_manager.hpp
src/color_dialog_delegate.hpp
src/overlay_manager_view.hpp)
-qt5_wrap_ui(UIS resource/image_overlay.ui)
+qt5_wrap_ui(UIS resource/image_overlay.ui resource/configuration_dialog.ui)
add_library(rqt_image_overlay SHARED
${SOURCES}
${UIS})
diff --git a/rqt_image_overlay/resource/configuration_dialog.ui b/rqt_image_overlay/resource/configuration_dialog.ui
new file mode 100644
index 0000000..68f1a91
--- /dev/null
+++ b/rqt_image_overlay/resource/configuration_dialog.ui
@@ -0,0 +1,66 @@
+
+
+ ConfigurationDialog
+
+
+
+ 0
+ 0
+
+
+
+ Image Overlay configuration
+
+
+ -
+
+
-
+
+
+ Waiting &window (sec)
+
+
+ Time to wait before composing an image. If overlay messages arrive much later than the image, increase this value.
+
+
+ window
+
+
+
+ -
+
+
+ 3
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ dialog_button_box
+ accepted()
+ configuration_dialog
+ accept()
+
+
+ dialog_button_box
+ rejected()
+ configuration_dialog
+ reject()
+
+
+
diff --git a/rqt_image_overlay/src/compositor.cpp b/rqt_image_overlay/src/compositor.cpp
index 5a578c1..2aad132 100644
--- a/rqt_image_overlay/src/compositor.cpp
+++ b/rqt_image_overlay/src/compositor.cpp
@@ -22,13 +22,24 @@ namespace rqt_image_overlay
{
Compositor::Compositor(
- const ImageManager & imageManager, const OverlayManager & overlayManager,
- float frequency, rclcpp::Duration window)
-: imageManager(imageManager), overlayManager(overlayManager), window(window)
+ const ImageManager & imageManager, const OverlayManager & overlayManager, float frequency)
+: imageManager(imageManager), overlayManager(overlayManager),
+ window_(std::make_shared(0, 300000000))
{
startTimer(1000.0 / frequency);
}
+void Compositor::setWindow(const rclcpp::Duration & window)
+{
+ std::atomic_store(&window_, std::make_shared(window));
+}
+
+rclcpp::Duration Compositor::getWindow() const
+{
+ auto window = std::atomic_load(&window_);
+ return *window;
+}
+
void Compositor::setCallableSetImage(std::function)> setImage)
{
this->setImage = setImage;
@@ -40,6 +51,9 @@ std::shared_ptr Compositor::compose()
return nullptr;
}
+ // Get window_ value through the getWindow() method so that it is thread-safe
+ auto window = getWindow();
+
rclcpp::Time targetTime = systemClock.now() - window;
auto [composition, imageHeaderTime] = imageManager.getClosestImageAndHeaderTime(targetTime);
OverlayTimeInfo overlayTimeInfo{targetTime, imageHeaderTime};
diff --git a/rqt_image_overlay/src/compositor.hpp b/rqt_image_overlay/src/compositor.hpp
index efc4c05..637ec67 100644
--- a/rqt_image_overlay/src/compositor.hpp
+++ b/rqt_image_overlay/src/compositor.hpp
@@ -32,8 +32,11 @@ class Compositor : public QObject
public:
Compositor(
- const ImageManager & imageManager, const OverlayManager & overlayManager,
- float frequency, rclcpp::Duration window = rclcpp::Duration{0, 300000000});
+ const ImageManager & imageManager, const OverlayManager & overlayManager, float frequency);
+
+ // Thread safe setter/getter for window
+ void setWindow(const rclcpp::Duration & window);
+ rclcpp::Duration getWindow() const;
void setCallableSetImage(std::function)> setImage);
@@ -46,7 +49,11 @@ class Compositor : public QObject
std::function)> setImage;
- const rclcpp::Duration window; // Wait window for collecting messages before composing image
+ // Wait window for collecting messages before composing image.
+ // To access this value, use the getWindow() method to ensure thread-safety, even from within
+ // this class.
+ std::shared_ptr window_;
+
rclcpp::Clock systemClock{RCL_SYSTEM_TIME};
};
diff --git a/rqt_image_overlay/src/image_overlay.cpp b/rqt_image_overlay/src/image_overlay.cpp
index 00f0c08..6ec3d17 100644
--- a/rqt_image_overlay/src/image_overlay.cpp
+++ b/rqt_image_overlay/src/image_overlay.cpp
@@ -16,6 +16,7 @@
#include
#include
#include "./ui_image_overlay.h"
+#include "./ui_configuration_dialog.h"
#include "image_overlay.hpp"
#include "compositor.hpp"
#include "overlay_manager.hpp"
@@ -97,7 +98,7 @@ void ImageOverlay::saveSettings(
instance_settings.setValue("image_topic", QString::fromStdString(imageTopic.topic));
instance_settings.setValue("image_transport", QString::fromStdString(imageTopic.transport));
}
-
+ instance_settings.setValue("compositor_window", compositor->getWindow().seconds());
overlayManager->saveSettings(instance_settings);
}
@@ -112,6 +113,11 @@ void ImageOverlay::restoreSettings(
ui->image_topics_combo_box->setCurrentIndex(1);
}
+ if (instance_settings.contains("compositor_window")) {
+ auto window_double = instance_settings.value("compositor_window").toDouble();
+ auto duration = rclcpp::Duration::from_seconds(window_double);
+ compositor->setWindow(duration);
+ }
overlayManager->restoreSettings(instance_settings);
}
@@ -132,6 +138,24 @@ void ImageOverlay::fillOverlayMenu()
ui->add_overlay_button->setMenu(menu.get());
}
+bool ImageOverlay::hasConfiguration() const
+{
+ return true;
+}
+
+void ImageOverlay::triggerConfiguration()
+{
+ auto configuration_dialog = std::make_unique();
+ auto ui_configuration_dialog = std::make_unique();
+ ui_configuration_dialog->setupUi(configuration_dialog.get());
+ ui_configuration_dialog->window->setValue(compositor->getWindow().seconds());
+
+ if (configuration_dialog->exec() == QDialog::Accepted) {
+ auto window_seconds = ui_configuration_dialog->window->value();
+ compositor->setWindow(rclcpp::Duration::from_seconds(window_seconds));
+ }
+}
+
} // namespace rqt_image_overlay
diff --git a/rqt_image_overlay/src/image_overlay.hpp b/rqt_image_overlay/src/image_overlay.hpp
index 77377b4..5772bbd 100644
--- a/rqt_image_overlay/src/image_overlay.hpp
+++ b/rqt_image_overlay/src/image_overlay.hpp
@@ -42,6 +42,8 @@ class ImageOverlay : public rqt_gui_cpp::Plugin
void restoreSettings(
const qt_gui_cpp::Settings &,
const qt_gui_cpp::Settings & instanceSettings) override;
+ bool hasConfiguration() const override;
+ void triggerConfiguration() override;
public slots:
void removeOverlay();