|
|
@@ -2,6 +2,7 @@
|
|
|
#define SOPHIAR2_TRANSFORM_UTILITY_HPP
|
|
|
|
|
|
#include "core/basic_obj_types.hpp"
|
|
|
+#include "utility/config_utility.hpp"
|
|
|
#include "utility/coro_signal_group.hpp"
|
|
|
#include "utility/coro_worker.hpp"
|
|
|
#include "utility/simple_tristate_obj.hpp"
|
|
|
@@ -12,100 +13,145 @@
|
|
|
namespace sophiar {
|
|
|
|
|
|
inline coro_worker::pointer make_transform_inverter_func(const nlohmann::json &config) {
|
|
|
- assert(config.contains("input_obj_name"));
|
|
|
- assert(config.contains("output_obj_name"));
|
|
|
- assert(config["input_obj_name"].is_string());
|
|
|
- assert(config["output_obj_name"].is_string());
|
|
|
- auto input_obj_name = config["input_obj_name"].get<std::string>();
|
|
|
- auto output_obj_name = config["output_obj_name"].get<std::string>();
|
|
|
- auto input_obj_index = REGISTER_GLOBAL_OBJ(transform_obj, input_obj_name);
|
|
|
- auto output_obj_index = REGISTER_GLOBAL_OBJ(transform_obj, output_obj_name);
|
|
|
- auto worker = make_infinite_coro_worker(global_context, [=,
|
|
|
- input_helper = GLOBAL_OBJ_AUTO_DELEGATE(transform_obj, input_obj_index)]() mutable
|
|
|
- -> boost::asio::awaitable<bool> {
|
|
|
- co_await input_helper.coro_wait_update(false);
|
|
|
- auto ts = GLOBAL_OBJ_UPDATE_TS(input_obj_index);
|
|
|
- if (input_helper.empty()) [[unlikely]] {
|
|
|
- UPDATE_GLOBAL_OBJ_TS(transform_obj, output_obj_index, nullptr, ts);
|
|
|
- } else [[likely]] {
|
|
|
- auto new_trans = transform_obj::new_instance();
|
|
|
- new_trans->value = input_helper->value.inverse();
|
|
|
- UPDATE_GLOBAL_OBJ_TS(transform_obj, output_obj_index, new_trans, ts);
|
|
|
- }
|
|
|
- co_return true;
|
|
|
- });
|
|
|
+ auto input_var_index = LOAD_VARIABLE_INDEX(transform_obj, "input_var_name");
|
|
|
+ auto output_var_index = LOAD_VARIABLE_INDEX(transform_obj, "output_var_name");
|
|
|
+ auto worker = make_infinite_coro_worker(
|
|
|
+ [=,
|
|
|
+ input_helper = VARIABLE_MANUAL_DELEGATE(transform_obj, input_var_index)]() mutable
|
|
|
+ -> boost::asio::awaitable<bool> {
|
|
|
+ co_await input_helper.coro_wait_update();
|
|
|
+ auto ts = input_helper.get_last_update_ts();
|
|
|
+ if (input_helper.empty()) [[unlikely]] {
|
|
|
+ UPDATE_VARIABLE_WITH_TS(transform_obj, output_var_index, nullptr, ts);
|
|
|
+ } else [[likely]] {
|
|
|
+ UPDATE_VARIABLE_VAL_WITH_TS(transform_obj, output_var_index, input_helper->value.inverse(), ts);
|
|
|
+ }
|
|
|
+ co_return true;
|
|
|
+ });
|
|
|
return std::move(worker);
|
|
|
}
|
|
|
|
|
|
- scalarxyz_obj::value_type get_scalarxyz_from_json_list(const nlohmann::json &config) {
|
|
|
- assert(config.is_array());
|
|
|
- assert(config.size() == 3);
|
|
|
- double val[3];
|
|
|
- for (int i = 0; i < 3; ++i) {
|
|
|
- assert(config[i].is_number());
|
|
|
- val[i] = config[i].get<double>();
|
|
|
+ inline bool determine_is_transform_vector(const nlohmann::json &config) {
|
|
|
+ assert(config.contains("transform_type"));
|
|
|
+ if (config["transform_type"] == "point") {
|
|
|
+ return false;
|
|
|
+ } else if (config["transform_type"] == "vector") {
|
|
|
+ return true;
|
|
|
}
|
|
|
- return {val[0], val[1], val[2]};
|
|
|
+ assert(false);
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- template<bool IsVector>
|
|
|
- inline coro_worker::pointer make_fixed_scalarxyz_transformer(const nlohmann::json &config) {
|
|
|
- assert(config["transform_type"] == "point");
|
|
|
- auto fixed_value = get_scalarxyz_from_json_list(config["fixed_value"]);
|
|
|
- auto trans_obj_name = config["transform_obj_name"].get<std::string>();
|
|
|
- auto output_obj_name = config["output_obj_name"].get<std::string>();
|
|
|
- auto trans_obj_index = REGISTER_GLOBAL_OBJ(transform_obj, trans_obj_name);
|
|
|
- auto output_obj_index = REGISTER_GLOBAL_OBJ(scalarxyz_obj, output_obj_name);
|
|
|
- auto worker = make_infinite_coro_worker(global_context, [=,
|
|
|
- trans_helper = GLOBAL_OBJ_AUTO_DELEGATE(transform_obj, trans_obj_index)]() mutable
|
|
|
- -> boost::asio::awaitable<bool> {
|
|
|
- co_await trans_helper.coro_wait_update(false);
|
|
|
- auto ts = GLOBAL_OBJ_UPDATE_TS(trans_obj_index);
|
|
|
- if (trans_helper.empty()) [[unlikely]] {
|
|
|
- UPDATE_GLOBAL_OBJ_TS(scalarxyz_obj, output_obj_index, nullptr, ts);
|
|
|
- } else [[likely]] {
|
|
|
- auto new_value = scalarxyz_obj::new_instance();
|
|
|
- if constexpr (IsVector) {
|
|
|
- new_value->value = trans_helper->value.linear() * fixed_value;
|
|
|
- } else {
|
|
|
- new_value->value = trans_helper->value * fixed_value;
|
|
|
- }
|
|
|
- UPDATE_GLOBAL_OBJ_TS(scalarxyz_obj, output_obj_index, new_value, ts);
|
|
|
- }
|
|
|
- co_return true;
|
|
|
- });
|
|
|
+ // 变换矩阵变换, 变换目标不动
|
|
|
+ inline coro_worker::pointer make_target_fixed_scalarxyz_transformer(const nlohmann::json &config) {
|
|
|
+ auto is_vector = determine_is_transform_vector(config);
|
|
|
+ auto fixed_value = scalarxyz_obj::read_value_from_json_array(config["target_value"]);
|
|
|
+ auto trans_var_index = LOAD_VARIABLE_INDEX(transform_obj, "transform_var_name");
|
|
|
+ auto output_var_index = LOAD_VARIABLE_INDEX(scalarxyz_obj, "output_var_name");
|
|
|
+ auto worker = make_infinite_coro_worker(
|
|
|
+ [=,
|
|
|
+ trans_helper = VARIABLE_MANUAL_DELEGATE(transform_obj, trans_var_index)]() mutable
|
|
|
+ -> boost::asio::awaitable<bool> {
|
|
|
+ co_await trans_helper.coro_wait_update();
|
|
|
+ auto ts = trans_helper.get_last_update_ts();
|
|
|
+ if (trans_helper.empty()) [[unlikely]] {
|
|
|
+ UPDATE_VARIABLE_WITH_TS(scalarxyz_obj, output_var_index, nullptr, ts);
|
|
|
+ } else [[likely]] {
|
|
|
+ UPDATE_VARIABLE_VAL_WITH_TS(scalarxyz_obj, output_var_index,
|
|
|
+ is_vector ?
|
|
|
+ (trans_helper->value.linear() * fixed_value) :
|
|
|
+ (trans_helper->value * fixed_value),
|
|
|
+ ts);
|
|
|
+ }
|
|
|
+ co_return true;
|
|
|
+ });
|
|
|
+ return std::move(worker);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 变换矩阵不变, 变换目标移动
|
|
|
+ inline coro_worker::pointer make_transform_fixed_scalarxyz_transformer(const nlohmann::json &config) {
|
|
|
+ auto is_vector = determine_is_transform_vector(config);
|
|
|
+ auto fixed_trans = transform_obj::read_value_from_json_array(config["transform_value"]);
|
|
|
+ auto input_var_index = LOAD_VARIABLE_INDEX(scalarxyz_obj, "input_var_name");
|
|
|
+ auto output_var_index = LOAD_VARIABLE_INDEX(scalarxyz_obj, "output_var_name");
|
|
|
+ auto worker = make_infinite_coro_worker(
|
|
|
+ [=,
|
|
|
+ xyz_helper = VARIABLE_MANUAL_DELEGATE(scalarxyz_obj, input_var_index)]() mutable
|
|
|
+ -> boost::asio::awaitable<bool> {
|
|
|
+ co_await xyz_helper.coro_wait_update();
|
|
|
+ auto ts = xyz_helper.get_last_update_ts();
|
|
|
+ if (xyz_helper.empty()) [[unlikely]] {
|
|
|
+ UPDATE_VARIABLE_WITH_TS(scalarxyz_obj, output_var_index, nullptr, ts);
|
|
|
+ } else [[likely]] {
|
|
|
+ UPDATE_VARIABLE_VAL_WITH_TS(scalarxyz_obj, output_var_index,
|
|
|
+ is_vector ?
|
|
|
+ (fixed_trans.linear() * xyz_helper->value) :
|
|
|
+ (fixed_trans * xyz_helper->value),
|
|
|
+ ts);
|
|
|
+ }
|
|
|
+ co_return true;
|
|
|
+ });
|
|
|
+ return std::move(worker);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 变换矩阵变换, 变换目标移动
|
|
|
+ template<bool IsSynced>
|
|
|
+ inline auto make_dynamic_scalarxyz_transformer(const nlohmann::json &config) {
|
|
|
+ auto is_vector = determine_is_transform_vector(config);
|
|
|
+ auto trans_var_index = LOAD_VARIABLE_INDEX(transform_obj, "transform_var_name");
|
|
|
+ auto input_var_index = LOAD_VARIABLE_INDEX(scalarxyz_obj, "input_var_name");
|
|
|
+ auto output_var_index = LOAD_VARIABLE_INDEX(scalarxyz_obj, "output_var_name");
|
|
|
+
|
|
|
+ static constexpr auto cond_func = [](auto &mask) { return IsSynced ? mask.all() : mask.any(); };
|
|
|
+ auto signal_group = coro_signal_group<cond_func>::new_instance();
|
|
|
+ signal_group->add_watcher(REQUIRE_VARIABLE_WATCHER(trans_var_index));
|
|
|
+ signal_group->add_watcher(REQUIRE_VARIABLE_WATCHER(input_var_index));
|
|
|
+ auto signal_watcher = signal_group->new_watcher();
|
|
|
+ signal_group->start();
|
|
|
+ auto exit_func = SIGNAL_GROUP_AUTO_CLOSER(signal_group);
|
|
|
+
|
|
|
+ auto worker = make_infinite_coro_worker(
|
|
|
+ [=,
|
|
|
+ watcher = std::move(signal_watcher)]() mutable
|
|
|
+ -> boost::asio::awaitable<bool> {
|
|
|
+ co_await watcher.coro_wait(false);
|
|
|
+ auto ts = watcher.get_last_update_ts();
|
|
|
+ auto trans = QUERY_VARIABLE(transform_obj, trans_var_index);
|
|
|
+ auto xyz = QUERY_VARIABLE(scalarxyz_obj, input_var_index);
|
|
|
+ if (trans == nullptr || xyz == nullptr) [[unlikely]] {
|
|
|
+ UPDATE_VARIABLE_WITH_TS(scalarxyz_obj, output_var_index, nullptr, ts);
|
|
|
+ } else [[likely]] {
|
|
|
+ UPDATE_VARIABLE_VAL_WITH_TS(scalarxyz_obj, output_var_index,
|
|
|
+ is_vector ?
|
|
|
+ (trans->value.linear() * xyz->value) :
|
|
|
+ (trans->value * xyz->value),
|
|
|
+ ts);
|
|
|
+ }
|
|
|
+ co_return true;
|
|
|
+ }, std::move(exit_func));
|
|
|
+
|
|
|
return std::move(worker);
|
|
|
}
|
|
|
|
|
|
inline coro_worker::pointer make_scalarxyz_transformer(const nlohmann::json &config) {
|
|
|
- assert(config.contains("transform_obj_name"));
|
|
|
- assert(config.contains("output_obj_name"));
|
|
|
- assert(config["transform_obj_name"].is_string());
|
|
|
- assert(config["output_obj_name"].is_string());
|
|
|
- assert(config.contains("transform_type"));
|
|
|
- assert(config["transform_type"].is_string());
|
|
|
- auto trans_type = config["transform_type"].get<std::string>();
|
|
|
- if (config.contains("fixed_value")) {
|
|
|
- if (trans_type == "vector") {
|
|
|
- return make_fixed_scalarxyz_transformer<true>(config);
|
|
|
- } else {
|
|
|
- assert(trans_type == "point");
|
|
|
- return make_fixed_scalarxyz_transformer<false>(config);
|
|
|
- }
|
|
|
- } else {
|
|
|
- assert(config.contains("input_obj_name"));
|
|
|
- assert(config["input_obj_name"].is_string());
|
|
|
- // TODO 实现 dynamic_scalaxyz_transformer
|
|
|
- assert(false);
|
|
|
- return nullptr;
|
|
|
+ auto is_transform_dynamic = config.contains("transform_var_name");
|
|
|
+ auto is_target_dynamic = config.contains("input_var_name");
|
|
|
+ if (is_transform_dynamic && is_target_dynamic) { // dynamic
|
|
|
+ auto is_synced = TRY_LOAD_BOOL_ITEM("synced", false);
|
|
|
+ return is_synced ?
|
|
|
+ make_dynamic_scalarxyz_transformer<true>(config) :
|
|
|
+ make_dynamic_scalarxyz_transformer<false>(config);
|
|
|
+ } else if (!is_transform_dynamic) { // transform fixed
|
|
|
+ assert(is_target_dynamic);
|
|
|
+ return make_transform_fixed_scalarxyz_transformer(config);
|
|
|
+ } else { // target fixed
|
|
|
+ assert(is_transform_dynamic);
|
|
|
+ return make_target_fixed_scalarxyz_transformer(config);
|
|
|
}
|
|
|
assert(false);
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
- using transform_inverter = simple_tristate_obj_wrapper<make_transform_inverter_func>;
|
|
|
- using scalarxyz_transformer = simple_tristate_obj_wrapper<make_scalarxyz_transformer>;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
#endif //SOPHIAR2_TRANSFORM_UTILITY_HPP
|