Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor plotting and block handling #177

Merged
merged 26 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
654da5f
h -> hpp
ivan-cukic Mar 20, 2024
2391bc8
Fix header
frankosterfeld Apr 12, 2024
c1fe674
Refactor GP node handling
frankosterfeld Apr 11, 2024
7733707
Refactor plot rendering
frankosterfeld Apr 18, 2024
5f93ef2
Print signal name, apply name to GR block
frankosterfeld Apr 18, 2024
8afb73c
Simplify block lists
frankosterfeld Apr 19, 2024
23fd1a5
Rename DataSink to ImPlotSink, move to blocks/
frankosterfeld Apr 19, 2024
a68b19a
Restyled by clang-format
restyled-commits Apr 19, 2024
9b30a18
Restyled by cmake-format
restyled-commits Apr 19, 2024
0d1504a
Block/BlockType handling cleanup
frankosterfeld Apr 19, 2024
2d255a1
Minimal simplification
frankosterfeld Apr 19, 2024
da78803
Make RemoteSource independent of App
frankosterfeld Apr 19, 2024
aa6751a
Do not warn about unknown scheduler block
frankosterfeld Apr 19, 2024
1057c02
Add missing header
frankosterfeld Apr 19, 2024
da6e515
Restyled by clang-format
restyled-commits Apr 19, 2024
2fa6631
actually throw exceptions...
frankosterfeld Apr 19, 2024
5805a12
Make color a property of the GR sink block
frankosterfeld Apr 21, 2024
8afaab8
Remove special UI-side block type handler for ImPlotSink
frankosterfeld Apr 22, 2024
d5bcb04
Use PluginLoader for GR block creation
frankosterfeld Apr 23, 2024
838fd8d
Simplify type handling and registration
frankosterfeld Apr 23, 2024
b247ea0
Fix color parameters
frankosterfeld Apr 23, 2024
030323d
Use GP yaml parsing for flowgraph
frankosterfeld Apr 23, 2024
725989b
ImPlotSink: Restrict types that can be instantiated
frankosterfeld Apr 23, 2024
5ebac59
Restyled by clang-format
restyled-commits Apr 23, 2024
e43af19
Restyled by cmake-format
restyled-commits Apr 23, 2024
a2374a7
Minor fixes
frankosterfeld Apr 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/Dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ FetchContent_Declare(
FetchContent_Declare(
opencmw-cpp
GIT_REPOSITORY https://github.com/fair-acc/opencmw-cpp.git
GIT_TAG 0fb3758c3ffe7707aa5e0bd2ad25f9e8fb19f79d# main as of 2024-04-26
GIT_TAG 0fb3758c3ffe7707aa5e0bd2ad25f9e8fb19f79d # main as of 2024-04-26
)

FetchContent_Declare(
Expand Down
24 changes: 14 additions & 10 deletions src/service/dashboard/defaultDashboard.flowgraph
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
blocks:
- name: FFT
id: FFT
id: gr::blocks::fft::FFT
- name: sum sigs
id: opendigitizer::Arithmetic
- name: sine source 1
id: opendigitizer::SineSource
parameters:
frequency: 0.100000
- name: source for sink 1
id: sink_source
- name: source for sink 2
id: sink_source
- name: remote source 1
id: opendigitizer::RemoteSource
parameters:
remote_uri: https://localhost:8080/GnuRadio/Acquisition?channelNameFilter=test
- name: sink 1
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0xff0000
- name: sink 2
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0x00ff00
- name: sink 3
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0x0000ff
- name: sink 4
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0xffff00
connections:
- [sine source 1, 0, FFT, 0]
- [FFT, 0, sink 1, 0]
- [sine source 1, 0, sum sigs, 0]
- [source for sink 1, 0, sum sigs, 1]
- [FFT, 0, sum sigs, 1]
- [sum sigs, 0, sink 2, 0]
- [sine source 1, 0, sink 3, 0]
- [remote source 1, 0, sink 4, 0]
2 changes: 1 addition & 1 deletion src/service/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#endif

#include "build_configuration.hpp"
#include "settings.h"
#include "settings.hpp"

// TODO use built-in GR blocks

Expand Down
4 changes: 2 additions & 2 deletions src/ui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ set(sources
flowgraph.cpp
flowgraphitem.cpp
dashboard.cpp
flowgraph/datasink.cpp
dashboardpage.cpp
opendashboardpage.cpp
imguiutils.cpp
opendashboardpage.cpp
remotesignalsources.cpp)

set(GNURADIO_PREFIX
Expand Down Expand Up @@ -183,6 +182,7 @@ target_link_libraries(
gnuradio-algorithm
gr-basic
gr-fourier
gr-testing
fftw
vir
pmtv)
Expand Down
39 changes: 26 additions & 13 deletions src/ui/app.h → src/ui/app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
#define IMGUI_DEFINE_MATH_OPERATORS true
#endif

#include "common.h"
#include "dashboard.h"
#include "dashboardpage.h"
#include "flowgraphitem.h"
#include "opendashboardpage.h"
#include "common.hpp"
#include "dashboard.hpp"
#include "dashboardpage.hpp"
#include "flowgraphitem.hpp"
#include "opendashboardpage.hpp"

#include <gnuradio-4.0/Message.hpp>
#include <gnuradio-4.0/Scheduler.hpp>
Expand Down Expand Up @@ -82,16 +82,21 @@
handler = std::make_unique<HandlerImpl<T>>(std::forward<Args>(args)...);
}

explicit operator bool() const { return handler != nullptr; };
explicit operator bool() const { return handler != nullptr; };

void sendMessage(const gr::Message &msg) { handler->sendMessage(msg); }
void handleMessages(FlowGraph &fg) { handler->handleMessages(fg); }
std::string_view uniqueName() const {
return handler ? handler->uniqueName() : "";
}

void sendMessage(const gr::Message &msg) { handler->sendMessage(msg); }
void handleMessages(FlowGraph &fg) { handler->handleMessages(fg); }

private:
struct Handler {
virtual ~Handler() = default;
virtual void sendMessage(const gr::Message &msg) = 0;
virtual void handleMessages(FlowGraph &fg) = 0;
virtual ~Handler() = default;
virtual std::string_view uniqueName() const = 0;
virtual void sendMessage(const gr::Message &msg) = 0;
virtual void handleMessages(FlowGraph &fg) = 0;
};

template<typename TScheduler>
Expand All @@ -114,6 +119,7 @@
}
gr::sendMessage<gr::message::Command::Subscribe>(_toScheduler, _scheduler.unique_name, gr::block::property::kLifeCycleState, {}, "UI");
gr::sendMessage<gr::message::Command::Subscribe>(_toScheduler, "", gr::block::property::kSetting, {}, "UI");
gr::sendMessage<gr::message::Command::Get>(_toScheduler, "", gr::block::property::kSetting, {}, "UI");

_thread = std::thread([this]() {
if (auto e = _scheduler.changeStateTo(gr::lifecycle::State::INITIALISED); !e) {
Expand All @@ -135,7 +141,9 @@
});
}

void sendMessage(const gr::Message &msg) final {
std::string_view uniqueName() const override { return _scheduler.unique_name; }

void sendMessage(const gr::Message &msg) final {
_toScheduler.streamWriter().publish([&](auto &output) { output[0] = msg; }, 1);
}

Expand All @@ -160,7 +168,8 @@
std::unique_ptr<Handler> handler;
};

SchedWrapper _scheduler;
SchedWrapper _scheduler;
std::vector<gr::BlockModel *> _toolbarBlocks;

public:
App() noexcept { setStyle(Style::Light); }
Expand All @@ -177,7 +186,7 @@
emscripten_run_script(script.c_str());
#else
if (fork() == 0) {
execl(executable.c_str(), executable.c_str(), nullptr);

Check warning on line 189 in src/ui/app.hpp

View check run for this annotation

codefactor.io / CodeFactor

src/ui/app.hpp#L189

Possible OS Command Injection (CWE-78) (flawfinder7-execl)
}
#endif
}
Expand Down Expand Up @@ -248,6 +257,10 @@
_scheduler.emplace<Scheduler>(std::forward<Graph>(graph), schedulerThreadPool);
}

std ::string_view schedulerUniqueName() const {
return _scheduler.uniqueName();
}

void sendMessage(const gr::Message &msg) {
if (_scheduler) {
_scheduler.sendMessage(msg);
Expand Down
8 changes: 4 additions & 4 deletions src/ui/app_header/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
add_library(
app_header INTERFACE
"fair_header.h"
PopupMenu.hpp
)
app_header
INTERFACE
"fair_header.hpp"
PopupMenu.hpp)
target_include_directories(app_header INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(app_header INTERFACE stb fmt)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <stb_image.h>
#include <string_view>

#include "../app.h"
#include "../app.hpp"
#include <PopupMenu.hpp>

CMRC_DECLARE(ui_assets);
Expand Down
26 changes: 13 additions & 13 deletions src/ui/assets/sampleDashboards/DemoDashboard.grc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ blocks:
- name: sum sigs
id: opendigitizer::Arithmetic
- name: FFT
id: FFT
id: gr::blocks::fft::FFT
- name: sine source 1
id: opendigitizer::SineSource
parameters:
Expand All @@ -12,21 +12,21 @@ blocks:
parameters:
frequency: 1.300000
- name: sink 1
id: sink
- name: source for sink 1
id: sink_source
id: opendigitizer::ImPlotSink
parameters:
color: 0xff0000
- name: sink 2
id: sink
- name: source for sink 2
id: sink_source
id: opendigitizer::ImPlotSink
parameters:
color: 0x00ff00
- name: sink 3
id: sink
- name: source for sink 3
id: sink_source
id: opendigitizer::ImPlotSink
parameters:
color: 0x0000ff
- name: sink 4
id: sink
- name: source for sink 4
id: sink_source
id: opendigitizer::ImPlotSink
parameters:
color: 0xffff00
connections:
- [sine source 1, 0, sum sigs, 0]
- [sine source 3, 0, sum sigs, 1]
Expand Down
30 changes: 19 additions & 11 deletions src/ui/assets/sampleDashboards/ExtendedDemoDashboard.grc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ blocks:
- name: sum sigs3
id: opendigitizer::Arithmetic
- name: FFT
id: FFT
id: gr::blocks::fft::FFT
- name: sine source 3
id: opendigitizer::SineSource
parameters:
Expand All @@ -23,22 +23,30 @@ blocks:
id: opendigitizer::SineSource
parameters:
frequency: 0.400000
- name: source for sink 1
id: sink_source
- name: source for sink 2
id: sink_source
- name: sink 1
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0xff0000
- name: sink 2
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0x00ff00
- name: sink 3
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0x0000ff
- name: sink 4
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0xffff00
- name: sink 5
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0x00ffff
- name: sink 6
id: sink
id: opendigitizer::ImPlotSink
parameters:
color: 0xff00ff
connections:
- [sine source 3, 0, sum sigs1, 0]
- [sine source 4, 0, sum sigs1, 1]
Expand Down
2 changes: 2 additions & 0 deletions src/ui/blocks/Arithmetic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,6 @@ struct Arithmetic : public gr::Block<Arithmetic<T>> {

ENABLE_REFLECTION_FOR_TEMPLATE(opendigitizer::Arithmetic, in1, in2, out, operation)

auto registerArithmetic = gr::registerBlock<opendigitizer::Arithmetic, float, double>(gr::globalBlockRegistry());

#endif
81 changes: 81 additions & 0 deletions src/ui/blocks/ImPlotSink.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#ifndef OPENDIGITIZER_IMPLOTSINK_HPP
#define OPENDIGITIZER_IMPLOTSINK_HPP

#include "meta.hpp"

#include <gnuradio-4.0/Block.hpp>
#include <gnuradio-4.0/DataSet.hpp>
#include <gnuradio-4.0/HistoryBuffer.hpp>

#include <imgui.h>
#include <implot.h>
#include <limits>

namespace opendigitizer {

template<typename T>
struct ImPlotSink : public gr::Block<ImPlotSink<T>,
gr::BlockingIO<false>, gr::SupportedTypes<float, double, gr::DataSet<float>, gr::DataSet<double>>, gr::Drawable<gr::UICategory::ChartPane, "Dear ImGui">> {
gr::PortIn<T> in;
uint32_t color = 0xff0000; ///< RGB color for the plot // TODO use better type, support configurable colors for datasets?
std::string signal_name;
std::string signal_unit;
float signal_min = std::numeric_limits<float>::lowest();
float signal_max = std::numeric_limits<float>::max();

public:
std::conditional_t<meta::is_dataset_v<T>, T, gr::HistoryBuffer<T>> data = [] {
if constexpr (meta::is_dataset_v<T>) {
return T{};
} else {
return gr::HistoryBuffer<T>{ 65536 };
}
}();

gr::work::Status processBulk(gr::ConsumableSpan auto &input) noexcept {
if constexpr (meta::is_dataset_v<T>) {
data = input.back();
} else {
data.push_back_bulk(input);
}
std::ignore = input.consume(input.size());
return gr::work::Status::OK;
}

gr::work::Status
draw() noexcept {
[[maybe_unused]] const gr::work::Status status = this->invokeWork();
if constexpr (meta::is_dataset_v<T>) {
if (data.extents.empty()) {
return gr::work::Status::OK;
}

for (std::int32_t i = 0; i < data.extents[0]; ++i) {
const auto n = data.extents[1];
ImPlot::PlotLine(data.signal_names[static_cast<std::size_t>(i)].c_str(), data.signal_values.data() + n * i, n);
}
} else {
const auto &label = signal_name.empty() ? this->name.value : signal_name;
if (data.empty()) {
// Plot one single dummy value so that the sink shows up in the plot legend
T v = {};
ImPlot::PlotLine(label.c_str(), &v, 1);
} else {
ImPlot::SetNextLineStyle(ImGui::ColorConvertU32ToFloat4((color << 8) | 0xff));
ImPlot::HideNextItem(false, ImPlotCond_Always);
const auto span = std::span(data.begin(), data.end());
// TODO should we limit this to the last N (N might be UI-dependent) samples?
ImPlot::PlotLine(label.c_str(), span.data(), static_cast<int>(span.size()));
}
}
return gr::work::Status::OK;
}
};

} // namespace opendigitizer

ENABLE_REFLECTION_FOR_TEMPLATE(opendigitizer::ImPlotSink, in, color, signal_name, signal_unit, signal_min, signal_max);

auto registerImPlotSink = gr::registerBlock<opendigitizer::ImPlotSink, float, double, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry());

#endif
Loading
Loading