|
@@ -0,0 +1,160 @@
|
|
|
|
|
+#include "probe_p2p.h"
|
|
|
|
|
+#include "core/local_connection.h"
|
|
|
|
|
+#include "imgui_utility.h"
|
|
|
|
|
+#include "main_impl/impl_types.h"
|
|
|
|
|
+#include "vtk_viewer.h"
|
|
|
|
|
+
|
|
|
|
|
+#include <functional>
|
|
|
|
|
+#include <random>
|
|
|
|
|
+#include <queue>
|
|
|
|
|
+
|
|
|
|
|
+using namespace sophiar;
|
|
|
|
|
+
|
|
|
|
|
+extern local_connection sophiar_conn;
|
|
|
|
|
+extern std::unique_ptr<vtk_viewer> augment_viewer;
|
|
|
|
|
+extern std::unique_ptr<camera_related> left;
|
|
|
|
|
+
|
|
|
|
|
+struct probe_p2p::impl {
|
|
|
|
|
+
|
|
|
|
|
+ bool enable = false;
|
|
|
|
|
+ bool is_running = false;
|
|
|
|
|
+ bool use_camera_coord = true;
|
|
|
|
|
+ std::optional<float> last_dis_err, last_angle_err;
|
|
|
|
|
+ std::string probe_var_name;
|
|
|
|
|
+ Eigen::Isometry3d augment_probe_pose; // in camera or tracker
|
|
|
|
|
+ vtkSmartPointer<vtkActor> real_probe_actor;
|
|
|
|
|
+ vtkSmartPointer<vtkActor> augment_probe_actor;
|
|
|
|
|
+ std::queue<std::function<void()>> eq; // local event queue
|
|
|
|
|
+
|
|
|
|
|
+ ~impl() {
|
|
|
|
|
+ // TODO deconstruct earlier
|
|
|
|
|
+// augment_viewer->remove_actor(real_probe_actor);
|
|
|
|
|
+// augment_viewer->remove_actor(augment_probe_actor);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ static impl *create(const create_config &conf) {
|
|
|
|
|
+ auto ret = new impl{};
|
|
|
|
|
+ ret->real_probe_actor = create_actor(conf.probe_model_path);
|
|
|
|
|
+ ret->augment_probe_actor = create_actor(conf.probe_model_path);
|
|
|
|
|
+ augment_viewer->add_actor(ret->real_probe_actor);
|
|
|
|
|
+ augment_viewer->add_actor(ret->augment_probe_actor);
|
|
|
|
|
+ ret->probe_var_name = conf.probe_var_name;
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void process() {
|
|
|
|
|
+ if (!enable) return;
|
|
|
|
|
+ while (!eq.empty()) { // handle events from UI
|
|
|
|
|
+ eq.front()();
|
|
|
|
|
+ eq.pop();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!is_running) {
|
|
|
|
|
+ real_probe_actor->SetVisibility(false);
|
|
|
|
|
+ augment_probe_actor->SetVisibility(false);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ augment_probe_actor->SetVisibility(true);
|
|
|
|
|
+ auto real_trans = sophiar_conn.query_transform_variable(probe_var_name);
|
|
|
|
|
+ update_actor_pose(real_probe_actor, real_trans);
|
|
|
|
|
+
|
|
|
|
|
+ // recalculate augment pose
|
|
|
|
|
+ auto augment_trans = augment_probe_pose;
|
|
|
|
|
+ if (use_camera_coord) {
|
|
|
|
|
+ augment_trans = left->transform * augment_trans;
|
|
|
|
|
+ update_actor_pose(augment_probe_actor, augment_trans);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // calculate error
|
|
|
|
|
+ if (!real_trans.has_value()) {
|
|
|
|
|
+ last_dis_err = {};
|
|
|
|
|
+ last_angle_err = {};
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ static auto origin = Eigen::Vector3d::Zero();
|
|
|
|
|
+ auto real_origin = real_trans.value() * origin;
|
|
|
|
|
+ auto augment_origin = augment_trans * origin;
|
|
|
|
|
+ last_dis_err = (real_origin - augment_origin).norm();
|
|
|
|
|
+ auto real_z = real_trans->rotation().col(2);
|
|
|
|
|
+ auto augment_z = augment_trans.rotation().col(2);
|
|
|
|
|
+ auto angle_err = std::acos(real_z.dot(augment_z));
|
|
|
|
|
+ angle_err *= 180.0 / std::numbers::pi;
|
|
|
|
|
+ last_angle_err = 180.0 - angle_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void prepare_target() {
|
|
|
|
|
+ constexpr auto x_min = -50, x_max = 50;
|
|
|
|
|
+ constexpr auto y_min = -50, y_max = 50;
|
|
|
|
|
+ constexpr auto z_min = 400, z_max = 600;
|
|
|
|
|
+
|
|
|
|
|
+ static std::random_device rd;
|
|
|
|
|
+ static std::mt19937 gen{rd()};
|
|
|
|
|
+ static auto rand_x = std::uniform_real_distribution<double>(x_min, x_max);
|
|
|
|
|
+ static auto rand_y = std::uniform_real_distribution<double>(y_min, y_max);
|
|
|
|
|
+ static auto rand_z = std::uniform_real_distribution<double>(z_min, z_max);
|
|
|
|
|
+ static auto rand_q = std::uniform_real_distribution<double>(-1, 1);
|
|
|
|
|
+
|
|
|
|
|
+ static auto augment_base_trans = Eigen::AngleAxisd{ // Flip at Z axis
|
|
|
|
|
+ std::numbers::pi, Eigen::Vector3d::UnitX()};
|
|
|
|
|
+ auto augment_transl = Eigen::Translation3d{rand_x(gen), rand_y(gen), rand_z(gen)};
|
|
|
|
|
+ auto quat_vec = Eigen::Vector4d{rand_q(gen), rand_q(gen), rand_q(gen), rand_q(gen)};
|
|
|
|
|
+ quat_vec /= quat_vec.norm();
|
|
|
|
|
+ auto augment_rot = Eigen::Quaterniond{quat_vec};
|
|
|
|
|
+ augment_probe_pose = augment_transl * augment_rot * augment_base_trans;
|
|
|
|
|
+ if (use_camera_coord) {
|
|
|
|
|
+ update_actor_pose(augment_probe_actor,
|
|
|
|
|
+ left->transform * augment_probe_pose); // transform to world coordinate
|
|
|
|
|
+ } else {
|
|
|
|
|
+ augment_probe_pose = left->transform * augment_probe_pose;
|
|
|
|
|
+ update_actor_pose(augment_probe_actor, augment_probe_pose);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void show_ui() {
|
|
|
|
|
+ {
|
|
|
|
|
+ auto guard = imgui_disable_guard{is_running};
|
|
|
|
|
+ ImGui::Checkbox("Enable", &enable);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!enable) return;
|
|
|
|
|
+ {
|
|
|
|
|
+ auto guard = imgui_disable_guard{is_running};
|
|
|
|
|
+ ImGui::SameLine();
|
|
|
|
|
+ ImGui::Checkbox("Camera Coordinate", &use_camera_coord);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!is_running) {
|
|
|
|
|
+ if (ImGui::Button("Start")) {
|
|
|
|
|
+ eq.emplace([&] {
|
|
|
|
|
+ prepare_target();
|
|
|
|
|
+ is_running = true;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if (ImGui::Button("Record")) {
|
|
|
|
|
+ eq.emplace([&] {
|
|
|
|
|
+ // TODO
|
|
|
|
|
+ is_running = false;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ show_variable("Distance Error", last_dis_err);
|
|
|
|
|
+ show_variable("Angular Error", last_angle_err);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+probe_p2p::~probe_p2p() = default;
|
|
|
|
|
+
|
|
|
|
|
+probe_p2p *probe_p2p::create(const create_config &conf) {
|
|
|
|
|
+ auto pimpl = impl::create(conf);
|
|
|
|
|
+// if (pimpl == nullptr) return nullptr;
|
|
|
|
|
+ auto ret = new probe_p2p;
|
|
|
|
|
+ ret->pimpl.reset(pimpl);
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void probe_p2p::process() {
|
|
|
|
|
+ pimpl->process();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void probe_p2p::show_ui() {
|
|
|
|
|
+ pimpl->show_ui();
|
|
|
|
|
+}
|