From 0d9509cc9ff3d7c209869ff36c4e340897895314 Mon Sep 17 00:00:00 2001 From: Benjamin Morgan Date: Wed, 26 Jun 2024 14:48:10 +0200 Subject: [PATCH] all: Improve DataBroker interface for common types --- engine/src/registrar.hpp | 49 +++++++++++++++------- plugins/basic/src/basic.cpp | 41 ++---------------- plugins/speedometer/src/speedometer.cpp | 19 ++++----- runtime/include/cloe/data_broker.hpp | 37 +++++++++++++++- runtime/include/cloe/registrar.hpp | 30 ++++++++++--- runtime/include/cloe/trigger/nil_event.hpp | 1 + tests/test_lua04_schedule_test.lua | 12 +++--- 7 files changed, 111 insertions(+), 78 deletions(-) diff --git a/engine/src/registrar.hpp b/engine/src/registrar.hpp index cc88edfc8..abc47ed5a 100644 --- a/engine/src/registrar.hpp +++ b/engine/src/registrar.hpp @@ -21,11 +21,14 @@ #pragma once -#include // for unique_ptr<>, shared_ptr<> -#include // for string +#include // for unique_ptr<>, shared_ptr<> +#include // for string +#include // for string_view -#include // for cloe::Registrar +#include // for logger::get +#include // for cloe::Registrar +#include "config.hpp" // for CLOE_TRIGGER_PATH_DELIMITER, ... #include "coordinator.hpp" // for Coordinator #include "server.hpp" // for Server, ServerRegistrar @@ -59,55 +62,69 @@ class Registrar : public cloe::Registrar { server_registrar_->register_api_handler(endpoint, t, h); } - std::unique_ptr clone() const { + [[nodiscard]] std::unique_ptr clone() const { return std::make_unique(*this, "", "", ""); } std::unique_ptr with_static_prefix(const std::string& prefix) const override { - assert(prefix.size() > 0); + assert(!prefix.empty()); return std::make_unique(*this, "", prefix, ""); } std::unique_ptr with_api_prefix(const std::string& prefix) const override { - assert(prefix.size() > 0); + assert(!prefix.empty()); return std::make_unique(*this, "", "", prefix); } std::unique_ptr with_trigger_prefix(const std::string& prefix) const override { - assert(prefix.size() > 0 && prefix[0] != '_'); + assert(!prefix.empty() && prefix[0] != '_'); return std::make_unique(*this, prefix, "", ""); } - std::string trigger_key(const std::string& name) { - assert(name.size() != 0); + [[nodiscard]] std::string make_prefix(std::string_view name, std::string_view delim) const { + assert(!name.empty()); - if (trigger_prefix_.size() == 0) { + if (trigger_prefix_.empty()) { // This only works for Cloe internal triggers. - return name; + return std::string(name); } + + std::string prefix = trigger_prefix_; if (name == "_") { // Special case: "_" means we can actually use just trigger_prefix_. // This might cause a problem if we name a plugin the same as one // of the internal Cloe triggers... - return trigger_prefix_; + return prefix; } - return trigger_prefix_ + "/" + name; + prefix += delim; + prefix += name; + return prefix; + } + + [[nodiscard]] std::string make_trigger_name(std::string_view name) const { + return make_prefix(name, CLOE_TRIGGER_PATH_DELIMITER); + } + + [[nodiscard]] std::string make_signal_name(std::string_view name) const override { + auto sname = make_prefix(name, CLOE_SIGNAL_PATH_DELIMITER); + coordinator_->logger()->debug("Register signal: {}", sname); + return sname; } void register_action(cloe::ActionFactoryPtr&& af) override { - coordinator_->register_action(trigger_key(af->name()), std::move(af)); + coordinator_->register_action(make_trigger_name(af->name()), std::move(af)); } void register_event( cloe::EventFactoryPtr&& ef, std::shared_ptr storage) override { - coordinator_->register_event(trigger_key(ef->name()), std::move(ef), storage); + coordinator_->register_event(make_trigger_name(ef->name()), std::move(ef), storage); } sol::table register_lua_table() override { return coordinator_->register_lua_table(trigger_prefix_); } - cloe::DataBroker& data_broker() const override { + [[nodiscard]] cloe::DataBroker& data_broker() const override { assert(data_broker_ != nullptr); return *data_broker_; } diff --git a/plugins/basic/src/basic.cpp b/plugins/basic/src/basic.cpp index d208218a9..b8e9fa8d2 100644 --- a/plugins/basic/src/basic.cpp +++ b/plugins/basic/src/basic.cpp @@ -397,45 +397,10 @@ class BasicController : public Controller { } void enroll(Registrar& r) override { - auto& db = r.data_broker(); if (this->veh_) { - auto& vehicle = this->veh_->name(); - { - std::string name1 = fmt::format("vehicles.{}.{}.acc", vehicle, name()); - auto acc_signal = db.declare(name1); - acc_signal->set_getter( - [this]() -> const cloe::controller::basic::AccConfiguration& { - return this->acc_.config; - }); - acc_signal->set_setter( - [this](const cloe::controller::basic::AccConfiguration& value) { - this->acc_.config = value; - }); - } - { - std::string name1 = fmt::format("vehicles.{}.{}.aeb", vehicle, name()); - auto aeb_signal = db.declare(name1); - aeb_signal->set_getter( - [this]() -> const cloe::controller::basic::AebConfiguration& { - return this->aeb_.config; - }); - aeb_signal->set_setter( - [this](const cloe::controller::basic::AebConfiguration& value) { - this->aeb_.config = value; - }); - } - { - std::string name1 = fmt::format("vehicles.{}.{}.lka", vehicle, name()); - auto lka_signal = db.declare(name1); - lka_signal->set_getter( - [this]() -> const cloe::controller::basic::LkaConfiguration& { - return this->lka_.config; - }); - lka_signal->set_setter( - [this](const cloe::controller::basic::LkaConfiguration& value) { - this->lka_.config = value; - }); - } + r.declare_signal("acc", &acc_.config); + r.declare_signal("aeb", &aeb_.config); + r.declare_signal("lka", &lka_.config); } auto lua = r.register_lua_table(); diff --git a/plugins/speedometer/src/speedometer.cpp b/plugins/speedometer/src/speedometer.cpp index 1159fbb50..6dc7457f5 100644 --- a/plugins/speedometer/src/speedometer.cpp +++ b/plugins/speedometer/src/speedometer.cpp @@ -38,22 +38,19 @@ struct SpeedometerConf : public fable::Confable { class Speedometer : public cloe::Component { public: - Speedometer(const std::string& name, const SpeedometerConf&, std::shared_ptr ego) + Speedometer(const std::string& name, const SpeedometerConf& /*conf*/, + std::shared_ptr ego) : Component(name, "provides an event trigger to evaluate speed in km/h"), sensor_(ego) {} - virtual ~Speedometer() noexcept = default; + ~Speedometer() noexcept override = default; void enroll(cloe::Registrar& r) override { callback_kmph_ = r.register_event("kmph", "vehicle speed in km/h"); - auto& db = r.data_broker(); - { - std::string signal_name = fmt::format("components.{}.kmph", name()); - auto signal = db.declare(signal_name); - signal->set_getter( - [this]() -> double { return cloe::utility::EgoSensorCanon(sensor_).velocity_as_kmph(); }); - } + auto kmph_signal = r.declare_signal("kmph"); + kmph_signal->set_getter( + [this]() -> double { return cloe::utility::EgoSensorCanon(sensor_).velocity_as_kmph(); }); } cloe::Duration process(const cloe::Sync& sync) override { @@ -63,7 +60,7 @@ class Speedometer : public cloe::Component { } fable::Json active_state() const override { - return fable::Json{{"kmph", utility::EgoSensorCanon(sensor_).velocity_as_kmph()}}; + return fable::Json{{"kmph", cloe::utility::EgoSensorCanon(sensor_).velocity_as_kmph()}}; } private: @@ -75,7 +72,7 @@ class Speedometer : public cloe::Component { DEFINE_COMPONENT_FACTORY(SpeedometerFactory, SpeedometerConf, "speedometer", "provide an event trigger to evaluate speed in km/h") -DEFINE_COMPONENT_FACTORY_MAKE(SpeedometerFactory, Speedometer, EgoSensor) +DEFINE_COMPONENT_FACTORY_MAKE(SpeedometerFactory, Speedometer, cloe::EgoSensor) // Register factory as plugin entrypoint EXPORT_CLOE_PLUGIN(SpeedometerFactory) diff --git a/runtime/include/cloe/data_broker.hpp b/runtime/include/cloe/data_broker.hpp index 293cdf8d8..7f521c72b 100644 --- a/runtime/include/cloe/data_broker.hpp +++ b/runtime/include/cloe/data_broker.hpp @@ -1574,14 +1574,47 @@ class DataBroker { * \return Pointer to the specified signal */ template - SignalPtr declare(std::string_view new_name) { + SignalPtr declare(std::string_view name) { assert_static_type(); using compatible_type = databroker::compatible_base_t; declare(); SignalPtr signal = Signal::make(); - alias(signal, new_name); + alias(signal, name); + return signal; + } + + /** + * Declare a new signal and auto-implement getter and setter. + * + * \tparam T type of the signal value + * \param name name of the signal + * \param value_ptr pointer to signal value + * \return pointer to specified signal + */ + template + SignalPtr declare(std::string_view name, T* value_ptr) { + assert(value_ptr != nullptr); + auto signal = this->declare(name); + signal->template set_getter([value_ptr]() -> const T& { + return *value_ptr; + }); + signal->template set_setter([value_ptr](const T& value) { + *value_ptr = value; + }); + return signal; + } + + template + SignalPtr declare(std::string_view name, std::function getter, std::function setter) { + auto signal = this->declare(name); + if (getter) { + signal->template set_getter(getter); + } + if (setter) { + signal->template set_setter(setter); + } return signal; } diff --git a/runtime/include/cloe/registrar.hpp b/runtime/include/cloe/registrar.hpp index a357d9f05..2fbadadeb 100644 --- a/runtime/include/cloe/registrar.hpp +++ b/runtime/include/cloe/registrar.hpp @@ -26,11 +26,11 @@ #include // for string #include // for move +#include // for DataBroker +#include // for Handler +#include // for ActionFactory, EventFactory, Callback, ... +#include // for Json #include -#include // for DataBroker -#include // for Handler -#include // for ActionFactory, EventFactory, Callback, ... -#include // for Json namespace cloe { @@ -159,19 +159,37 @@ class Registrar { virtual std::unique_ptr with_static_prefix(const std::string& prefix) const = 0; /** - * Return a new Registrar with the given trigger prefix. + * Return a new Registrar with the given trigger and data broker prefix. * * The returned object should remain valid even if the object creating it * is destroyed. */ virtual std::unique_ptr with_trigger_prefix(const std::string& prefix) const = 0; + [[nodiscard]] virtual std::string make_signal_name(std::string_view name) const = 0; + /** * Register an ActionFactory. */ virtual void register_action(std::unique_ptr&&) = 0; - virtual DataBroker& data_broker() const = 0; + template + SignalPtr declare_signal(std::string_view name) { + return data_broker().declare(make_signal_name(name)); + } + + template + SignalPtr declare_signal(std::string_view name, T&& value_ptr) { + return data_broker().declare(make_signal_name(name), std::forward(value_ptr)); + } + + template + SignalPtr declare_signal(std::string_view name, GetterFunc&& getter, SetterFunc&& setter) { + return data_broker().declare(make_signal_name(name), std::forward(getter), + std::forward(setter)); + } + + [[nodiscard]] virtual DataBroker& data_broker() const = 0; /** * Construct and register an ActionFactory. diff --git a/runtime/include/cloe/trigger/nil_event.hpp b/runtime/include/cloe/trigger/nil_event.hpp index 7d4636cce..d97d1f722 100644 --- a/runtime/include/cloe/trigger/nil_event.hpp +++ b/runtime/include/cloe/trigger/nil_event.hpp @@ -25,6 +25,7 @@ #include // for string #include // for Conf, Json +#include // for DirectCallback #include // for Event, EventFactory, Action, ActionFactory #include // for _X_FACTORY, _X_CALLBACK diff --git a/tests/test_lua04_schedule_test.lua b/tests/test_lua04_schedule_test.lua index f7302de6f..639e59bab 100644 --- a/tests/test_lua04_schedule_test.lua +++ b/tests/test_lua04_schedule_test.lua @@ -18,15 +18,17 @@ cloe.schedule({ end, }) -local signals = { "vehicles.default.basic.acc" } -cloe.require_signals(signals) -cloe.record_signals(signals) +local Sig = { + VehAcc = "basic/acc" +} +cloe.require_signals_enum(Sig) +cloe.record_signals(Sig) cloe.record_signals( { ["acc_config.limit_acceleration"] = function() - return cloe.signal("vehicles.default.basic.acc").limit_acceleration + return cloe.signal(Sig.VehAcc).limit_acceleration end, ["acc_config.limit_deceleration"] = function() - return cloe.signal("vehicles.default.basic.acc").limit_deceleration + return cloe.signal(Sig.VehAcc).limit_deceleration end, })