remote_ar.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #include "remote_ar.h"
  2. #include "core/imgui_utility.hpp"
  3. #include "core/math_helper.hpp"
  4. #include "core/yaml_utility.hpp"
  5. #include "network/binary_utility.hpp"
  6. #include <boost/asio/post.hpp>
  7. using boost::asio::post;
  8. app_remote_ar::app_remote_ar(const create_config &_conf) {
  9. conf = _conf.ext_conf;
  10. asio_ctx = _conf.asio_ctx;
  11. cuda_ctx = _conf.cuda_ctx;
  12. // initialize object manager
  13. OBJ_SAVE(raw_left, image_u8c1());
  14. OBJ_SAVE(raw_right, image_u8c1());
  15. OBJ_SAVE(rgb_left, image_u8c3());
  16. OBJ_SAVE(rgb_right, image_u8c3());
  17. OBJ_SAVE(aug_left, image_u8c3());
  18. OBJ_SAVE(aug_right, image_u8c3());
  19. OBJ_SAVE(img_out, image_u8c4()); // ARGB
  20. OBJ_SAVE(guide_combine, image_u8c1());
  21. OBJ_SAVE(guide_info, data_type());
  22. OBJ_SAVE(guide_combine_rgb, image_u8c3());
  23. OBJ_SAVE(guide_img, image_u8c3());
  24. OBJ_SAVE(guide_depth_fake, image_u8c3());
  25. OBJ_SAVE(guide_depth, image_f32c1());
  26. // process callbacks caused by OBJ_SAVE
  27. asio_ctx->poll();
  28. // initialize sophiar
  29. sophiar_thread = std::make_unique<std::thread>([conf_path = LOAD_STR("sophiar_config")] {
  30. sophiar::run_sophiar(conf_path);
  31. });
  32. sophiar_conn = std::make_unique<sophiar_conn_type>();
  33. sophiar_start_var = LOAD_STR("sophiar_start_var");
  34. // initialize modules
  35. auto mvs_conf = mvs_camera_ui::create_config{.ctx = asio_ctx};
  36. mvs_conf.cameras.push_back({.dev_name = LOAD_STR("left_camera_name"), .img_name = raw_left});
  37. mvs_conf.cameras.push_back({.dev_name = LOAD_STR("right_camera_name"), .img_name = raw_right});
  38. mvs_cam = std::make_unique<mvs_camera_ui>(mvs_conf);
  39. mvs_cam->cap_info_sig.connect([this](auto info) {
  40. out_streamer->change_frame_rate(info.frame_rate);
  41. });
  42. auto stereo_info = stereo_camera_info::from_yaml(LOAD_SUB("stereo_info"));
  43. float view_angle = 0.0f;
  44. auto img_range = calc_valid_range(stereo_info.left, stereo_info.right, &view_angle);
  45. view_angle = glm::degrees(view_angle);
  46. auto cam_left_conf = image_process_ui::create_config{
  47. .in_name = raw_left, .out_name = rgb_left, .stream = &cam_left.stream
  48. };
  49. cam_left_conf.dev_info = {.valid_range = img_range, .cam_int = stereo_info.left};
  50. cam_left.img_proc = std::make_unique<image_process_ui>(cam_left_conf);
  51. auto cam_right_conf = image_process_ui::create_config{
  52. .in_name = raw_right, .out_name = rgb_right, .stream = &cam_right.stream
  53. };
  54. cam_right_conf.dev_info = {.valid_range = img_range, .cam_int = stereo_info.right};
  55. cam_right.img_proc = std::make_unique<image_process_ui>(cam_right_conf);
  56. cam_right.img_proc->sync_with(cam_left.img_proc.get());
  57. mvs_cam->cap_info_sig.connect([this](auto info) {
  58. cam_left.img_proc->change_config({.is_mono = info.is_mono});
  59. cam_right.img_proc->change_config({.is_mono = info.is_mono});
  60. });
  61. auto guide_in_conf = image_player::create_config{
  62. .img_name = guide_combine, .ext_name = guide_info,
  63. .ctx = asio_ctx,
  64. };
  65. guide_player = std::make_unique<image_player>(guide_in_conf);
  66. auto guide_cvt_conf = versatile_convertor::create_config{
  67. .in_name = guide_combine, .out_name = guide_combine_rgb,
  68. .cvt_opt = CVT_NV12_RGB, .stream = default_cuda_stream,
  69. };
  70. guide_cvt = std::make_unique<versatile_convertor>(guide_cvt_conf);
  71. auto guide_split_conf = versatile_convertor::create_config{
  72. .in_name = guide_combine_rgb, .out_name = guide_img, .ext_out = guide_depth_fake,
  73. .cvt_opt = CVT_HALF_SPLIT, .stream = default_cuda_stream,
  74. };
  75. guide_split = std::make_unique<versatile_convertor>(guide_split_conf);
  76. auto guide_decode_conf = versatile_convertor::create_config{
  77. .in_name = guide_depth_fake, .ext_in = guide_info, .out_name = guide_depth,
  78. .cvt_opt = CVT_FAKE_DECODE_800P, .stream = default_cuda_stream,
  79. };
  80. guide_decode = std::make_unique<versatile_convertor>(guide_decode_conf);
  81. auto guide_control_conf = depth_guide_controller::create_config{
  82. .img_in = guide_img, .depth_in = guide_depth, .img_out = guide_final
  83. };
  84. guide_controller = std::make_unique<depth_guide_controller>(guide_control_conf);
  85. auto aug_list_v1 = augment_manager::item_list_from_yaml(LOAD_LIST("augment_list"));
  86. auto aug_list = augment_manager_v2::item_list_from_v1(aug_list_v1);
  87. auto aug_conf = augment_manager_v2::create_config{
  88. .item_list = aug_list,
  89. .sophiar_conn = sophiar_conn.get(),
  90. .stream = default_cuda_stream,
  91. };
  92. aug_manager = std::make_unique<augment_manager_v2>(aug_conf);
  93. auto left_aug_conf = camera_augment_helper_v2::create_config{
  94. .camera = camera_augment_helper_v2::create_config::fixed_camera_config{
  95. .fov = view_angle, .transform_var = LOAD_STR("left_camera_transform_var"),
  96. },
  97. .sophiar_conn = sophiar_conn.get(), .manager = aug_manager.get()
  98. };
  99. cam_left.aug_helper = std::make_unique<camera_augment_helper_v2>(left_aug_conf);
  100. auto right_aug_conf = camera_augment_helper_v2::create_config{
  101. .camera = camera_augment_helper_v2::create_config::relative_camera_config{
  102. .parent = cam_left.aug_helper.get(),
  103. .transform = glm::inverse(to_mat4(stereo_info.transform)),
  104. },
  105. .sophiar_conn = sophiar_conn.get(), .manager = aug_manager.get()
  106. };
  107. cam_right.aug_helper = std::make_unique<camera_augment_helper_v2>(right_aug_conf);
  108. // auto right_aug_conf = left_aug_conf;
  109. // std::get<2>(right_aug_conf.camera).transform_var = LOAD_STR("right_camera_transform_var");
  110. // cam_right.aug_helper = std::make_unique<camera_augment_helper_v2>(right_aug_conf);
  111. //// cam_right.aug_helper->sync_with(cam_left.aug_helper.get());
  112. auto left_aug_ren_conf = image_augment_helper::create_config{
  113. .in_name = rgb_left, .out_name = aug_left,
  114. .flip_image = true, .stream = &cam_left.stream
  115. };
  116. left_aug_ren_conf.render_func_list.emplace_back([this] {
  117. cam_left.aug_helper->render();
  118. });
  119. left_aug_ren_conf.render_func_list.emplace_back([this] {
  120. guide_controller->render({.stream = &cam_left.stream}); // TODO: add camera specific options
  121. });
  122. cam_left.aug_render = std::make_unique<image_augment_helper>(left_aug_ren_conf);
  123. auto right_aug_ren_conf = image_augment_helper::create_config{
  124. .in_name = rgb_right, .out_name = aug_right,
  125. .flip_image = true, .stream = &cam_right.stream
  126. };
  127. right_aug_ren_conf.render_func_list.emplace_back([this] {
  128. cam_right.aug_helper->render();
  129. });
  130. right_aug_ren_conf.render_func_list.emplace_back([this] {
  131. guide_controller->render({.stream = &cam_right.stream});
  132. });
  133. cam_right.aug_render = std::make_unique<image_augment_helper>(right_aug_ren_conf);
  134. auto output_size = cv::Size(
  135. LOAD_NUMBER(int, "output_width"),
  136. LOAD_NUMBER(int, "output_height"));
  137. auto stereo_aug_conf = stereo_augment_helper::create_config{
  138. .left_name = aug_left, .right_name = aug_right,
  139. .out_name = img_out, .fbo_size = output_size,
  140. .flip_image = true, .stream = default_cuda_stream
  141. };
  142. stereo_aug = std::make_unique<stereo_augment_helper>(stereo_aug_conf);
  143. auto streamer_conf = image_streamer::create_config{
  144. .img_name = img_out, .asio_ctx = asio_ctx,
  145. .cuda_ctx = cuda_ctx, .stream = default_cuda_stream
  146. };
  147. out_streamer = std::make_unique<image_streamer>(streamer_conf);
  148. out_streamer->sig_req_size.connect([this](auto size) {
  149. post(*asio_ctx, [=, this] { stereo_aug->resize(size); });
  150. });
  151. auto bg_viewer_conf = image_viewer::create_config{
  152. .mode = VIEW_STEREO, .flip_y = false,
  153. .stream = default_cuda_stream,
  154. };
  155. auto &stereo_conf = bg_viewer_conf.extra.stereo;
  156. stereo_conf.c_fmt = COLOR_RGB;
  157. stereo_conf.left_name = aug_left;
  158. stereo_conf.right_name = aug_right;
  159. bg_viewer = std::make_unique<image_viewer>(bg_viewer_conf);
  160. // auto bg_viewer_conf = image_viewer::create_config{
  161. // .mode = VIEW_COLOR_DEPTH, .flip_y = true,
  162. // .stream = default_cuda_stream,
  163. // };
  164. // auto &bg_extra_conf = bg_viewer_conf.extra.color_depth;
  165. // bg_extra_conf.c_fmt = COLOR_RGB;
  166. // bg_extra_conf.c_name = guide_img;
  167. // bg_extra_conf.d_name = guide_depth;
  168. // bg_viewer = std::make_unique<image_viewer>(bg_viewer_conf);
  169. auto saver_conf = image_saver::create_config{.ctx = asio_ctx};
  170. saver_conf.img_list.emplace_back("Left", rgb_left);
  171. saver_conf.img_list.emplace_back("Right", rgb_right);
  172. debug_saver = std::make_unique<image_saver>(saver_conf);
  173. auto reg_conf = registration_config{
  174. .conn = sophiar_conn.get(),
  175. .probe_model_path = LOAD_STR("probe_model"),
  176. };
  177. reg.reset(registration::create(reg_conf));
  178. for (auto reg_item: LOAD_LIST("registration_list")) {
  179. auto item_conf = registration_target::from_yaml(reg_item);
  180. reg->add_target(item_conf);
  181. }
  182. }
  183. void app_remote_ar::start_tracking() {
  184. // sophiar_conn->start_object(sophiar_start_var);
  185. // work in another thread to prevent blocking
  186. auto t = std::thread([this] {
  187. auto conn = sophiar::local_connection();
  188. conn.start_object(sophiar_start_var);
  189. });
  190. t.detach();
  191. }
  192. app_remote_ar::~app_remote_ar() {
  193. // sophiar
  194. sophiar::stop_sophiar();
  195. sophiar_thread->join();
  196. }
  197. void app_remote_ar::show_ui() {
  198. if (ImGui::Begin("Remote AR Control")) {
  199. ImGui::PushItemWidth(200);
  200. if (ImGui::CollapsingHeader("Camera")) {
  201. auto id_guard = imgui_id_guard("camera");
  202. mvs_cam->show();
  203. ImGui::SeparatorText("Post-Processing");
  204. cam_left.img_proc->show();
  205. }
  206. if (ImGui::CollapsingHeader("Augment")) {
  207. ImGui::SeparatorText("Tracker");
  208. if (ImGui::Button("Start")) {
  209. start_tracking();
  210. }
  211. ImGui::SameLine();
  212. ImGui::Checkbox("Registration", &enable_reg);
  213. {
  214. ImGui::SeparatorText("Scene");
  215. auto id_guard = imgui_id_guard("augment_scene");
  216. aug_manager->show();
  217. }
  218. {
  219. ImGui::SeparatorText("Camera");
  220. auto id_guard = imgui_id_guard("augment_camera");
  221. cam_left.aug_helper->show();
  222. }
  223. }
  224. if (ImGui::CollapsingHeader("Depth Guide")) {
  225. auto id_guard = imgui_id_guard("depth_guide");
  226. guide_player->show();
  227. ImGui::SeparatorText("Display");
  228. guide_controller->show();
  229. }
  230. if (ImGui::CollapsingHeader("Stereo")) {
  231. auto id_guard = imgui_id_guard("stereo");
  232. stereo_aug->show();
  233. }
  234. if (ImGui::CollapsingHeader("Streamer")) {
  235. auto id_guard = imgui_id_guard("streamer");
  236. out_streamer->show();
  237. }
  238. if (ImGui::CollapsingHeader("Debug")) {
  239. if (ImGui::TreeNode("Background")) {
  240. bg_viewer->show();
  241. ImGui::TreePop();
  242. }
  243. if (ImGui::TreeNode("Memory Pool")) {
  244. if (ImGui::Button("Purge")) {
  245. post(*asio_ctx, [] { g_memory_manager->purify(); });
  246. }
  247. ImGui::TreePop();
  248. }
  249. if (ImGui::TreeNode("Performance")) {
  250. ImGui::Text("UI Refresh Rate: %.2fms", perf_timer.query().interval);
  251. ImGui::TreePop();
  252. }
  253. if (ImGui::TreeNode("Image Saver")) {
  254. debug_saver->show();
  255. ImGui::TreePop();
  256. }
  257. }
  258. ImGui::PopItemWidth();
  259. }
  260. ImGui::End();
  261. if (enable_reg) {
  262. reg->process();
  263. reg->show();
  264. }
  265. perf_timer.record();
  266. }
  267. void app_remote_ar::render_background() {
  268. bg_viewer->render();
  269. }