From 8f3ca447dd04de52ce6923f1e2001391ec31f560 Mon Sep 17 00:00:00 2001 From: Mobilizes Date: Sun, 16 Jun 2024 16:58:27 +0700 Subject: [PATCH 01/16] refactor: use jitsuyo config --- CMakeLists.txt | 4 +- include/shisen_cpp/config/utils/config.hpp | 44 -------------- include/shisen_cpp/node/shisen_cpp_node.hpp | 1 - .../grpc/call_data_get_capture_setting.cpp | 6 +- .../grpc/call_data_save_capture_setting.cpp | 5 +- .../grpc/call_data_set_capture_setting.cpp | 3 +- src/shisen_cpp/config/grpc/config.cpp | 6 +- src/shisen_cpp/config/utils/config.cpp | 57 ------------------- 8 files changed, 12 insertions(+), 114 deletions(-) delete mode 100644 include/shisen_cpp/config/utils/config.hpp delete mode 100644 src/shisen_cpp/config/utils/config.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fa76690..72adb40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ find_package(keisan REQUIRED) find_package(OpenCV REQUIRED) find_package(rclcpp REQUIRED) find_package(shisen_interfaces REQUIRED) +find_package(jitsuyo REQUIRED) find_package(sensor_msgs REQUIRED) find_package(std_msgs REQUIRED) find_package(Protobuf CONFIG REQUIRED) @@ -39,7 +40,6 @@ add_library(${PROJECT_NAME} SHARED "src/${PROJECT_NAME}/config/grpc/call_data_get_image.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_save_capture_setting.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_set_capture_setting.cpp" - "src/${PROJECT_NAME}/config/utils/config.cpp" "src/${PROJECT_NAME}/utility/capture_setting.cpp" "src/${PROJECT_NAME}/utility/interface.cpp" "src/${PROJECT_NAME}/node/shisen_cpp_node.cpp" @@ -72,6 +72,7 @@ ament_target_dependencies(${PROJECT_NAME} OpenCV rclcpp shisen_interfaces + jitsuyo sensor_msgs cv_bridge std_msgs @@ -82,6 +83,7 @@ ament_target_dependencies(${PROJECT_NAME}_exported OpenCV rclcpp shisen_interfaces + jitsuyo sensor_msgs cv_bridge std_msgs) diff --git a/include/shisen_cpp/config/utils/config.hpp b/include/shisen_cpp/config/utils/config.hpp deleted file mode 100644 index f8e9187..0000000 --- a/include/shisen_cpp/config/utils/config.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2024 ICHIRO ITS -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#ifndef SHISEN_CPP__CONFIG__UTILS__CONFIG_HPP_ -#define SHISEN_CPP__CONFIG__UTILS__CONFIG_HPP_ - -#include - -namespace shisen_cpp -{ - -class Config -{ -public: - explicit Config(const std::string & path); - - std::string get_capture_setting(const std::string & key) const; - void save_capture_setting(const nlohmann::json & capture_data); - nlohmann::json get_grpc_config() const; - -private: - std::string path; -}; - -} // namespace shisen_cpp - -#endif // SHISEN_CPP__CONFIG__UTILS__CONFIG_HPP_ diff --git a/include/shisen_cpp/node/shisen_cpp_node.hpp b/include/shisen_cpp/node/shisen_cpp_node.hpp index c306c47..3e22e03 100644 --- a/include/shisen_cpp/node/shisen_cpp_node.hpp +++ b/include/shisen_cpp/node/shisen_cpp_node.hpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp b/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp index 2f9b7e2..04ab59c 100644 --- a/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp +++ b/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp @@ -20,9 +20,9 @@ #include #include -#include #include #include +#include namespace shisen_cpp { @@ -46,9 +46,9 @@ void CallDataGetCaptureSetting::WaitForRequest() void CallDataGetCaptureSetting::HandleRequest() { - Config config(path_); + std::string capture_setting = jitsuyo::load_config(path_, "capture_settings.json").dump(); try { - reply_.set_json_capture(config.get_capture_setting("capture")); + reply_.set_json_capture(capture_setting); RCLCPP_INFO(rclcpp::get_logger("Get config"), "config has been sent!"); } catch (nlohmann::json::exception & e) { RCLCPP_ERROR(rclcpp::get_logger("Publish config"), e.what()); diff --git a/src/shisen_cpp/config/grpc/call_data_save_capture_setting.cpp b/src/shisen_cpp/config/grpc/call_data_save_capture_setting.cpp index cc10f4b..8a0d0f7 100644 --- a/src/shisen_cpp/config/grpc/call_data_save_capture_setting.cpp +++ b/src/shisen_cpp/config/grpc/call_data_save_capture_setting.cpp @@ -21,9 +21,9 @@ #include #include #include -#include #include #include +#include namespace shisen_cpp { @@ -47,13 +47,12 @@ void CallDataSaveCaptureSetting::WaitForRequest() void CallDataSaveCaptureSetting::HandleRequest() { - Config config(path_); try { std::string json_string = request_.json_capture(); std::replace(json_string.begin(), json_string.end(), '\\', ' '); nlohmann::json capture_data = nlohmann::json::parse(json_string); - config.save_capture_setting(capture_data); + jitsuyo::save_config(path_, "capture_settings.json", capture_data); RCLCPP_INFO(rclcpp::get_logger("Save config"), "config has been saved! "); } catch (nlohmann::json::exception & e) { RCLCPP_ERROR(rclcpp::get_logger("Save config"), e.what()); diff --git a/src/shisen_cpp/config/grpc/call_data_set_capture_setting.cpp b/src/shisen_cpp/config/grpc/call_data_set_capture_setting.cpp index de3a206..8b1510b 100644 --- a/src/shisen_cpp/config/grpc/call_data_set_capture_setting.cpp +++ b/src/shisen_cpp/config/grpc/call_data_set_capture_setting.cpp @@ -20,9 +20,9 @@ #include #include -#include #include #include +#include namespace shisen_cpp { @@ -46,7 +46,6 @@ void CallDataSetCaptureSetting::WaitForRequest() void CallDataSetCaptureSetting::HandleRequest() { - Config config(path_); try { CaptureSetting capture_setting; diff --git a/src/shisen_cpp/config/grpc/config.cpp b/src/shisen_cpp/config/grpc/config.cpp index a6095ba..d69c9a0 100644 --- a/src/shisen_cpp/config/grpc/config.cpp +++ b/src/shisen_cpp/config/grpc/config.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include using grpc::ServerBuilder; using namespace std::chrono_literals; @@ -50,9 +50,9 @@ void ConfigGrpc::SignIntHandler(int signum) void ConfigGrpc::Run(const std::string & path, std::shared_ptr camera_node) { - Config config(path); + nlohmann::json grpc_config = jitsuyo::load_config(path, "grpc.json"); std::string server_address = - absl::StrFormat("0.0.0.0:%d", config.get_grpc_config()["port"].get()); + absl::StrFormat("0.0.0.0:%d", grpc_config["port"].get()); ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); diff --git a/src/shisen_cpp/config/utils/config.cpp b/src/shisen_cpp/config/utils/config.cpp deleted file mode 100644 index 854ad28..0000000 --- a/src/shisen_cpp/config/utils/config.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2024 ICHIRO ITS -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#include - -#include -#include -#include - -namespace shisen_cpp -{ -Config::Config(const std::string & path) : path(path) {} - -std::string Config::get_capture_setting(const std::string & key) const -{ - if (key == "capture") { - std::ifstream capture_file(path + "capture_settings.json"); - nlohmann::json capture_data = nlohmann::json::parse(capture_file); - return capture_data.dump(); - } - - return ""; -} - -nlohmann::json Config::get_grpc_config() const -{ - std::ifstream grpc_file(path + "grpc.json"); - nlohmann::json grpc_data = nlohmann::json::parse(grpc_file); - grpc_file.close(); - return grpc_data; -} - -void Config::save_capture_setting(const nlohmann::json & capture_data) -{ - std::ofstream capture_file(path + "capture_settings.json", std::ios::out | std::ios::trunc); - capture_file << std::setw(2) << capture_data << std::endl; - capture_file.close(); -} - -} // namespace shisen_cpp From e94f5f21fb280e7ef00bf628f1f0627d5264236f Mon Sep 17 00:00:00 2001 From: hiikariri Date: Mon, 17 Jun 2024 04:43:32 +0700 Subject: [PATCH 02/16] feat: adapt main to remove ros arguments, add ros2 launch --- CMakeLists.txt | 11 +++++++++- launch/shisen_cpp_launch.py | 40 +++++++++++++++++++++++++++++++++++++ src/shisen_cpp_main.cpp | 14 ++++++------- 3 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 launch/shisen_cpp_launch.py diff --git a/CMakeLists.txt b/CMakeLists.txt index fa76690..d669f7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,13 @@ if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() +# Set the build type to Debug if not specified +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug) +endif() + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic -fPIC) + add_compile_options(-Wall -Wextra -Wpedantic -fPIC -g3) endif() find_package(ament_cmake REQUIRED) @@ -93,6 +98,10 @@ target_link_libraries(${PROJECT_NAME} install(DIRECTORY "include" DESTINATION ".") +install(DIRECTORY + launch + DESTINATION "share/${PROJECT_NAME}") + install(TARGETS ${PROJECT_NAME} EXPORT export_${PROJECT_NAME} ARCHIVE DESTINATION "lib" diff --git a/launch/shisen_cpp_launch.py b/launch/shisen_cpp_launch.py new file mode 100644 index 0000000..561b6c8 --- /dev/null +++ b/launch/shisen_cpp_launch.py @@ -0,0 +1,40 @@ +# Copyright (c) 2024 ICHIRO ITS +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import os +import socket +from launch import LaunchDescription +from launch_ros.actions import Node + +def generate_launch_description(): + hostname = socket.gethostname() + config_path = os.path.expanduser(f'~/ros2-ws/configuration/{hostname}/camera/') + + return LaunchDescription([ + Node( + package='shisen_cpp', + executable='camera', + name='camera', + output='screen', + arguments=[config_path], + respawn=True, + respawn_delay=1 + ) + ]) diff --git a/src/shisen_cpp_main.cpp b/src/shisen_cpp_main.cpp index 9a978e1..8164772 100644 --- a/src/shisen_cpp_main.cpp +++ b/src/shisen_cpp_main.cpp @@ -26,7 +26,7 @@ int main(int argc, char ** argv) { - rclcpp::init(argc, argv); + auto args = rclcpp::init_and_remove_ros_arguments(argc, argv); shisen_cpp::Options options; options.field_of_view = 78; @@ -50,20 +50,20 @@ int main(int argc, char ** argv) try { int i = 1; int pos = 0; - while (i < argc) { - std::string arg = argv[i++]; + while (i < args.size()) { + std::string arg = args[i++]; if (arg[0] == '-') { if (arg == "-h" || arg == "--help") { std::cout << help_message << std::endl; return 1; } else if (arg == "--camera-prefix") { - options.camera_prefix = argv[i++]; + options.camera_prefix = args[i++]; } else if (arg == "--compression") { - options.compression_quality = atoi(argv[i++]); + options.compression_quality = stoi(args[i++]); } else if (arg == "--capture-fps") { - options.capture_fps = atoi(argv[i++]); + options.capture_fps = stoi(args[i++]); } else if (arg == "--field-of-view") { - options.field_of_view = atoi(argv[i++]); + options.field_of_view = stoi(args[i++]); } else { std::cout << "Unknown option `" << arg << "`!\n\n" << help_message << std::endl; return 1; From 9cc5398a30afb0caa5e485b9580eb182f8d75d11 Mon Sep 17 00:00:00 2001 From: hiikariri Date: Wed, 19 Jun 2024 18:55:02 +0700 Subject: [PATCH 03/16] fix: remove debug argument in Cmakelists, use const reference to prevent copy var --- CMakeLists.txt | 7 +------ src/shisen_cpp_main.cpp | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d669f7a..cad45cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,13 +10,8 @@ if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() -# Set the build type to Debug if not specified -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug) -endif() - if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic -fPIC -g3) + add_compile_options(-Wall -Wextra -Wpedantic -fPIC) endif() find_package(ament_cmake REQUIRED) diff --git a/src/shisen_cpp_main.cpp b/src/shisen_cpp_main.cpp index 8164772..359bc58 100644 --- a/src/shisen_cpp_main.cpp +++ b/src/shisen_cpp_main.cpp @@ -51,7 +51,7 @@ int main(int argc, char ** argv) int i = 1; int pos = 0; while (i < args.size()) { - std::string arg = args[i++]; + const std::string& arg = args[i++]; if (arg[0] == '-') { if (arg == "-h" || arg == "--help") { std::cout << help_message << std::endl; From c363ddf5372e449f1f51a56cbf9aae07b701be1d Mon Sep 17 00:00:00 2001 From: Mobilizes Date: Fri, 21 Jun 2024 01:39:10 +0700 Subject: [PATCH 04/16] refactor: use jitsuyo to load config --- src/shisen_cpp/camera/node/camera_node.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index 961f53e..6b27b1c 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -199,15 +199,11 @@ void CameraNode::configure_capture_setting(const CaptureSetting & capture_settin void CameraNode::load_configuration(const std::string & path) { - std::string ss = path + "capture_settings.json"; - - std::ifstream input(ss, std::ifstream::in); - if (!input.is_open()) { + nlohmann::json config = jitsuyo::load_config(path, "capture_settings.json"); + if (config.empty()) { throw std::runtime_error("Unable to open `" + ss + "`!"); } - nlohmann::json config = nlohmann::json::parse(input); - CaptureSetting capture_setting; // Get all config From 7bfdede4c60b221271af99bfa7181fb8e7dacffb Mon Sep 17 00:00:00 2001 From: mbsaloka Date: Fri, 21 Jun 2024 19:58:16 +0700 Subject: [PATCH 05/16] fix: fix calling undefined string --- src/shisen_cpp/camera/node/camera_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index 6b27b1c..84fe46f 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -201,7 +201,7 @@ void CameraNode::load_configuration(const std::string & path) { nlohmann::json config = jitsuyo::load_config(path, "capture_settings.json"); if (config.empty()) { - throw std::runtime_error("Unable to open `" + ss + "`!"); + throw std::runtime_error("Unable to open `" + path + "capture_settings.json`!"); } CaptureSetting capture_setting; From a9b865ad4e07835fd604dc2508e7de5700e27aec Mon Sep 17 00:00:00 2001 From: Mobilizes Date: Fri, 21 Jun 2024 23:20:12 +0700 Subject: [PATCH 06/16] refactor: change load config --- src/shisen_cpp/camera/node/camera_node.cpp | 4 ++-- .../config/grpc/call_data_get_capture_setting.cpp | 7 ++++++- src/shisen_cpp/config/grpc/config.cpp | 6 +++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index 84fe46f..ae0c607 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -199,8 +199,8 @@ void CameraNode::configure_capture_setting(const CaptureSetting & capture_settin void CameraNode::load_configuration(const std::string & path) { - nlohmann::json config = jitsuyo::load_config(path, "capture_settings.json"); - if (config.empty()) { + nlohmann::json config; + if (!jitsuyo::load_config(path, "capture_settings.json", config)) { throw std::runtime_error("Unable to open `" + path + "capture_settings.json`!"); } diff --git a/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp b/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp index 04ab59c..bfedc23 100644 --- a/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp +++ b/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp @@ -46,7 +46,12 @@ void CallDataGetCaptureSetting::WaitForRequest() void CallDataGetCaptureSetting::HandleRequest() { - std::string capture_setting = jitsuyo::load_config(path_, "capture_settings.json").dump(); + nlohmann::json data; + if (!jitsuyo::load_config(path_, "capture_settings.json", data)) { + RCLCPP_ERROR(rclcpp::get_logger("Get config"), "Failed to load config!"); + return; + } + std::string capture_setting = data.dump(); try { reply_.set_json_capture(capture_setting); RCLCPP_INFO(rclcpp::get_logger("Get config"), "config has been sent!"); diff --git a/src/shisen_cpp/config/grpc/config.cpp b/src/shisen_cpp/config/grpc/config.cpp index d69c9a0..e000c26 100644 --- a/src/shisen_cpp/config/grpc/config.cpp +++ b/src/shisen_cpp/config/grpc/config.cpp @@ -50,7 +50,11 @@ void ConfigGrpc::SignIntHandler(int signum) void ConfigGrpc::Run(const std::string & path, std::shared_ptr camera_node) { - nlohmann::json grpc_config = jitsuyo::load_config(path, "grpc.json"); + nlohmann::json grpc_config; + if (!jitsuyo::load_config(path, "grpc.json", grpc_config)) { + RCLCPP_ERROR(rclcpp::get_logger("ConfigGrpc"), "Failed to load grpc config"); + return; + } std::string server_address = absl::StrFormat("0.0.0.0:%d", grpc_config["port"].get()); From 93bb0a74e0c2cf127573c7321cbae64d0dd381e7 Mon Sep 17 00:00:00 2001 From: Mobilizes Date: Sat, 22 Jun 2024 02:28:33 +0700 Subject: [PATCH 07/16] refactor: use jitsuyo to load capture setting config --- src/shisen_cpp/camera/node/camera_node.cpp | 42 ++++++++++++---------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index ae0c607..234389e 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -24,6 +24,7 @@ #include #include #include +#include "jitsuyo/config.hpp" #include #include @@ -206,27 +207,30 @@ void CameraNode::load_configuration(const std::string & path) CaptureSetting capture_setting; - // Get all config - for (auto & item : config.items()) { - try { - if (item.key() == "brightness") { - capture_setting.brightness.set(item.value()); - } else if (item.key() == "contrast") { - capture_setting.contrast.set(item.value()); - } else if (item.key() == "saturation") { - capture_setting.saturation.set(item.value()); - } else if (item.key() == "temperature") { - capture_setting.temperature.set(item.value()); - } else if (item.key() == "exposure") { - capture_setting.exposure.set(item.value()); - } else if (item.key() == "gain") { - capture_setting.gain.set(item.value()); - } - } catch (nlohmann::json::parse_error & ex) { - throw std::runtime_error("Parse error at byte `" + std::to_string(ex.byte) + "`!"); - } + int setting_brightness; + int setting_contrast; + int setting_saturation; + int setting_temperature; + int setting_exposure; + int setting_gain; + + if (!jitsuyo::assign_val(config, "brightness", setting_brightness) || + !jitsuyo::assign_val(config, "contrast", setting_contrast) || + !jitsuyo::assign_val(config, "saturation", setting_saturation) || + !jitsuyo::assign_val(config, "temperature", setting_temperature) || + !jitsuyo::assign_val(config, "exposure", setting_exposure) || + !jitsuyo::assign_val(config, "gain", setting_gain)) + { + throw std::runtime_error("Failed to load config file"); } + capture_setting.brightness.set(setting_brightness); + capture_setting.contrast.set(setting_contrast); + capture_setting.saturation.set(setting_saturation); + capture_setting.temperature.set(setting_temperature); + capture_setting.exposure.set(setting_exposure); + capture_setting.gain.set(setting_gain); + configure_capture_setting(capture_setting); } From f2f13729edc93510506e3f41f90c0aeb23edd8eb Mon Sep 17 00:00:00 2001 From: Mobilizes Date: Sat, 22 Jun 2024 18:11:04 +0700 Subject: [PATCH 08/16] feat: add section error --- src/shisen_cpp/camera/node/camera_node.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index 234389e..0250639 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jitsuyo/config.hpp" +#include #include #include @@ -221,7 +221,8 @@ void CameraNode::load_configuration(const std::string & path) !jitsuyo::assign_val(config, "exposure", setting_exposure) || !jitsuyo::assign_val(config, "gain", setting_gain)) { - throw std::runtime_error("Failed to load config file"); + std::cout << "Error found at section `capture_settings`" << std::endl; + throw std::runtime_error("Failed to load config file `" + path + "capture_settings.json`"); } capture_setting.brightness.set(setting_brightness); From 4d6a9d2b1d69fe0e27715e2c52cd10430133d349 Mon Sep 17 00:00:00 2001 From: Mobilizes Date: Mon, 24 Jun 2024 23:31:59 +0700 Subject: [PATCH 09/16] fix: add jitsuyo dependency in xml --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 37085c8..9e680d5 100644 --- a/package.xml +++ b/package.xml @@ -8,6 +8,7 @@ MIT License ament_cmake cv_bridge + jitsuyo keisan libopencv-dev rclcpp From 7c00448905d97c835e8d90ffff9e7729e8e8574d Mon Sep 17 00:00:00 2001 From: mbsaloka Date: Mon, 1 Jul 2024 19:08:04 +0700 Subject: [PATCH 10/16] feat: add record image service --- CMakeLists.txt | 1 + .../shisen_cpp/camera/node/camera_node.hpp | 6 ++ .../config/grpc/call_data_record_image.hpp | 45 +++++++++++++++ src/shisen_cpp/camera/node/camera_node.cpp | 28 ++++++++-- .../config/grpc/call_data_record_image.cpp | 55 +++++++++++++++++++ src/shisen_cpp/config/grpc/config.cpp | 2 + 6 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 include/shisen_cpp/config/grpc/call_data_record_image.hpp create mode 100644 src/shisen_cpp/config/grpc/call_data_record_image.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fcb6170..7c84817 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ add_library(${PROJECT_NAME} SHARED "src/${PROJECT_NAME}/config/grpc/config.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_get_capture_setting.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_get_image.cpp" + "src/${PROJECT_NAME}/config/grpc/call_data_record_image.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_save_capture_setting.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_set_capture_setting.cpp" "src/${PROJECT_NAME}/utility/capture_setting.cpp" diff --git a/include/shisen_cpp/camera/node/camera_node.hpp b/include/shisen_cpp/camera/node/camera_node.hpp index cd80498..d0a5b9e 100644 --- a/include/shisen_cpp/camera/node/camera_node.hpp +++ b/include/shisen_cpp/camera/node/camera_node.hpp @@ -43,6 +43,7 @@ class CameraNode void update(); void on_mat_captured(cv::Mat mat); void on_camera_config(int width, int height); + void save_image(cv::Mat mat); CaptureSetting on_configure_capture_setting(const CaptureSetting & capture_setting); void configure_capture_setting(const CaptureSetting & capture_setting = CaptureSetting()); void load_configuration(const std::string & path); @@ -57,6 +58,9 @@ class CameraNode std::shared_ptr image_provider; std::shared_ptr camera_config_provider; + bool get_record_status() { return is_record_on; } + void set_record_status(bool status) { is_record_on = status; } + private: rclcpp::Node::SharedPtr node; CaptureSetting current_capture_setting; @@ -68,6 +72,8 @@ class CameraNode rclcpp::Service::SharedPtr configure_capture_setting_service; Options options; + + bool is_record_on; }; } // namespace shisen_cpp::camera diff --git a/include/shisen_cpp/config/grpc/call_data_record_image.hpp b/include/shisen_cpp/config/grpc/call_data_record_image.hpp new file mode 100644 index 0000000..84a3fea --- /dev/null +++ b/include/shisen_cpp/config/grpc/call_data_record_image.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2024 ICHIRO ITS +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef SHISEN_CPP__CONFIG__GRPC__CALL_DATA_RECORD_IMAGE_HPP__ +#define SHISEN_CPP__CONFIG__GRPC__CALL_DATA_RECORD_IMAGE_HPP__ + +#include +#include + +namespace shisen_cpp +{ +class CallDataRecordImage +: CallData +{ +public: + CallDataRecordImage( + shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, + const std::string & path, const std::shared_ptr& camera_node); + +protected: + void AddNextToCompletionQueue() override; + void WaitForRequest() override; + void HandleRequest() override; + std::shared_ptr camera_node_; +}; +} // namespace shisen_cpp + +#endif // SHISEN_CPP__CONFIG__GRPC__CALL_DATA_RECORD_IMAGE_HPP__ diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index 0250639..e69a6b1 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -18,23 +18,23 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include -#include -#include -#include + #include +#include #include #include +#include #include #include +#include #include namespace shisen_cpp::camera { CameraNode::CameraNode(rclcpp::Node::SharedPtr node, const Options & options) -: node(node), options(options) +: node(node), options(options), is_record_on(false) { } @@ -53,6 +53,7 @@ void CameraNode::update() if (!captured_mat.empty()) { on_mat_captured(captured_mat); on_camera_config(captured_mat.cols, captured_mat.rows); + } else { RCLCPP_WARN_ONCE(node->get_logger(), "Once, captured an empty mat!"); } @@ -69,6 +70,23 @@ void CameraNode::on_camera_config(int width, int height) camera_config_publisher->publish(camera_config_provider->get_camera_config()); } +void CameraNode::save_image(cv::Mat mat) +{ + auto now = std::chrono::system_clock::now(); + std::time_t now_time = std::chrono::system_clock::to_time_t(now); + + std::stringstream ss; + ss << std::put_time(std::localtime(&now_time), "%Y-%m-%d_%H-%M-%S"); + std::string timestamp = ss.str(); + + std::string filename = "image/" + timestamp + ".jpg"; + + bool result = cv::imwrite(filename, mat); + if (!result) { + RCLCPP_ERROR(node->get_logger(), "Failed to save image!"); + } +} + cv::Mat CameraNode::get_mat() { update(); diff --git a/src/shisen_cpp/config/grpc/call_data_record_image.cpp b/src/shisen_cpp/config/grpc/call_data_record_image.cpp new file mode 100644 index 0000000..4722168 --- /dev/null +++ b/src/shisen_cpp/config/grpc/call_data_record_image.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2024 ICHIRO ITS +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include +#include +#include +#include +#include + +namespace shisen_cpp +{ +CallDataRecordImage::CallDataRecordImage( + shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, + const std::string & path, const std::shared_ptr& camera_node) +: CallData(service, cq, path), camera_node_(camera_node) +{ + Proceed(); +} + +void CallDataRecordImage::AddNextToCompletionQueue() +{ + new CallDataRecordImage(service_, cq_, path_, camera_node_); +} + +void CallDataRecordImage::WaitForRequest() +{ + service_->RequestRecordImage(&ctx_, &request_, &responder_, cq_, cq_, this); +} + +void CallDataRecordImage::HandleRequest() +{ + try { + camera_node_->set_record_status(request_.record()); + } catch(const std::exception& e) { + RCLCPP_ERROR(rclcpp::get_logger("Record Image"), e.what()); + } +} +} // namespace shisen_cpp diff --git a/src/shisen_cpp/config/grpc/config.cpp b/src/shisen_cpp/config/grpc/config.cpp index e000c26..70533ba 100644 --- a/src/shisen_cpp/config/grpc/config.cpp +++ b/src/shisen_cpp/config/grpc/config.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ void ConfigGrpc::Run(const std::string & path, std::shared_ptr Date: Mon, 1 Jul 2024 21:07:02 +0700 Subject: [PATCH 11/16] feat: add record image service --- CMakeLists.txt | 3 +- .../grpc/call_data_get_record_status.hpp | 45 +++++++++++++++ ...ge.hpp => call_data_set_record_status.hpp} | 10 ++-- src/shisen_cpp/camera/node/camera_node.cpp | 4 +- .../grpc/call_data_get_record_status.cpp | 55 +++++++++++++++++++ ...ge.cpp => call_data_set_record_status.cpp} | 18 +++--- src/shisen_cpp/config/grpc/config.cpp | 6 +- 7 files changed, 123 insertions(+), 18 deletions(-) create mode 100644 include/shisen_cpp/config/grpc/call_data_get_record_status.hpp rename include/shisen_cpp/config/grpc/{call_data_record_image.hpp => call_data_set_record_status.hpp} (86%) create mode 100644 src/shisen_cpp/config/grpc/call_data_get_record_status.cpp rename src/shisen_cpp/config/grpc/{call_data_record_image.cpp => call_data_set_record_status.cpp} (74%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c84817..94a67fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,9 +38,10 @@ add_library(${PROJECT_NAME} SHARED "src/${PROJECT_NAME}/config/grpc/config.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_get_capture_setting.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_get_image.cpp" - "src/${PROJECT_NAME}/config/grpc/call_data_record_image.cpp" + "src/${PROJECT_NAME}/config/grpc/call_data_get_record_status.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_save_capture_setting.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_set_capture_setting.cpp" + "src/${PROJECT_NAME}/config/grpc/call_data_set_record_status.cpp" "src/${PROJECT_NAME}/utility/capture_setting.cpp" "src/${PROJECT_NAME}/utility/interface.cpp" "src/${PROJECT_NAME}/node/shisen_cpp_node.cpp" diff --git a/include/shisen_cpp/config/grpc/call_data_get_record_status.hpp b/include/shisen_cpp/config/grpc/call_data_get_record_status.hpp new file mode 100644 index 0000000..506b8c1 --- /dev/null +++ b/include/shisen_cpp/config/grpc/call_data_get_record_status.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2024 ICHIRO ITS +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef SHISEN_CPP__CONFIG__GRPC__CALL_DATA_GET_RECORD_STATUS_HPP__ +#define SHISEN_CPP__CONFIG__GRPC__CALL_DATA_GET_RECORD_STATUS_HPP__ + +#include +#include + +namespace shisen_cpp +{ +class CallDataGetRecordStatus +: CallData +{ +public: + CallDataGetRecordStatus( + shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, + const std::string & path, const std::shared_ptr& camera_node); + +protected: + void AddNextToCompletionQueue() override; + void WaitForRequest() override; + void HandleRequest() override; + std::shared_ptr camera_node_; +}; +} // namespace shisen_cpp + +#endif // SHISEN_CPP__CONFIG__GRPC__CALL_DATA_GET_RECORD_STATUS_HPP__ diff --git a/include/shisen_cpp/config/grpc/call_data_record_image.hpp b/include/shisen_cpp/config/grpc/call_data_set_record_status.hpp similarity index 86% rename from include/shisen_cpp/config/grpc/call_data_record_image.hpp rename to include/shisen_cpp/config/grpc/call_data_set_record_status.hpp index 84a3fea..7087714 100644 --- a/include/shisen_cpp/config/grpc/call_data_record_image.hpp +++ b/include/shisen_cpp/config/grpc/call_data_set_record_status.hpp @@ -18,19 +18,19 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#ifndef SHISEN_CPP__CONFIG__GRPC__CALL_DATA_RECORD_IMAGE_HPP__ -#define SHISEN_CPP__CONFIG__GRPC__CALL_DATA_RECORD_IMAGE_HPP__ +#ifndef SHISEN_CPP__CONFIG__GRPC__CALL_DATA_SET_RECORD_STATUS_HPP__ +#define SHISEN_CPP__CONFIG__GRPC__CALL_DATA_SET_RECORD_STATUS_HPP__ #include #include namespace shisen_cpp { -class CallDataRecordImage +class CallDataSetRecordStatus : CallData { public: - CallDataRecordImage( + CallDataSetRecordStatus( shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, const std::string & path, const std::shared_ptr& camera_node); @@ -42,4 +42,4 @@ class CallDataRecordImage }; } // namespace shisen_cpp -#endif // SHISEN_CPP__CONFIG__GRPC__CALL_DATA_RECORD_IMAGE_HPP__ +#endif // SHISEN_CPP__CONFIG__GRPC__CALL_DATA_SET_RECORD_STATUS_HPP__ diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index e69a6b1..64a4786 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -53,7 +53,9 @@ void CameraNode::update() if (!captured_mat.empty()) { on_mat_captured(captured_mat); on_camera_config(captured_mat.cols, captured_mat.rows); - + if (is_record_on) { + save_image(captured_mat); + } } else { RCLCPP_WARN_ONCE(node->get_logger(), "Once, captured an empty mat!"); } diff --git a/src/shisen_cpp/config/grpc/call_data_get_record_status.cpp b/src/shisen_cpp/config/grpc/call_data_get_record_status.cpp new file mode 100644 index 0000000..71ee365 --- /dev/null +++ b/src/shisen_cpp/config/grpc/call_data_get_record_status.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2024 ICHIRO ITS +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include +#include +#include +#include + +namespace shisen_cpp +{ +CallDataGetRecordStatus::CallDataGetRecordStatus( + shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, + const std::string & path, const std::shared_ptr& camera_node) +: CallData(service, cq, path), camera_node_(camera_node) +{ + Proceed(); +} + +void CallDataGetRecordStatus::AddNextToCompletionQueue() +{ + new CallDataGetRecordStatus(service_, cq_, path_, camera_node_); +} + +void CallDataGetRecordStatus::WaitForRequest() +{ + service_->RequestGetRecordStatus(&ctx_, &request_, &responder_, cq_, cq_, this); +} + +void CallDataGetRecordStatus::HandleRequest() +{ + try { + reply_.set_record(camera_node_->get_record_status()); + RCLCPP_INFO(rclcpp::get_logger("Get record status"), "status has been sent!"); + } catch(const std::exception& e) { + RCLCPP_ERROR(rclcpp::get_logger("Get Record Status"), e.what()); + } +} +} // namespace shisen_cpp diff --git a/src/shisen_cpp/config/grpc/call_data_record_image.cpp b/src/shisen_cpp/config/grpc/call_data_set_record_status.cpp similarity index 74% rename from src/shisen_cpp/config/grpc/call_data_record_image.cpp rename to src/shisen_cpp/config/grpc/call_data_set_record_status.cpp index 4722168..aa000e9 100644 --- a/src/shisen_cpp/config/grpc/call_data_record_image.cpp +++ b/src/shisen_cpp/config/grpc/call_data_set_record_status.cpp @@ -18,15 +18,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include #include -#include +#include #include #include namespace shisen_cpp { -CallDataRecordImage::CallDataRecordImage( +CallDataSetRecordStatus::CallDataSetRecordStatus( shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, const std::string & path, const std::shared_ptr& camera_node) : CallData(service, cq, path), camera_node_(camera_node) @@ -34,22 +33,23 @@ CallDataRecordImage::CallDataRecordImage( Proceed(); } -void CallDataRecordImage::AddNextToCompletionQueue() +void CallDataSetRecordStatus::AddNextToCompletionQueue() { - new CallDataRecordImage(service_, cq_, path_, camera_node_); + new CallDataSetRecordStatus(service_, cq_, path_, camera_node_); } -void CallDataRecordImage::WaitForRequest() +void CallDataSetRecordStatus::WaitForRequest() { - service_->RequestRecordImage(&ctx_, &request_, &responder_, cq_, cq_, this); + service_->RequestSetRecordStatus(&ctx_, &request_, &responder_, cq_, cq_, this); } -void CallDataRecordImage::HandleRequest() +void CallDataSetRecordStatus::HandleRequest() { try { camera_node_->set_record_status(request_.record()); + RCLCPP_INFO(rclcpp::get_logger("Set record status"), "status has been apply!"); } catch(const std::exception& e) { - RCLCPP_ERROR(rclcpp::get_logger("Record Image"), e.what()); + RCLCPP_ERROR(rclcpp::get_logger("Set Record Status"), e.what()); } } } // namespace shisen_cpp diff --git a/src/shisen_cpp/config/grpc/config.cpp b/src/shisen_cpp/config/grpc/config.cpp index 70533ba..0baadf9 100644 --- a/src/shisen_cpp/config/grpc/config.cpp +++ b/src/shisen_cpp/config/grpc/config.cpp @@ -22,9 +22,10 @@ #include #include #include -#include +#include #include #include +#include #include #include @@ -73,7 +74,8 @@ void ConfigGrpc::Run(const std::string & path, std::shared_ptr Date: Mon, 1 Jul 2024 23:08:41 +0700 Subject: [PATCH 12/16] fix: record image service --- CMakeLists.txt | 3 +- .../shisen_cpp/camera/node/camera_node.hpp | 5 -- ..._status.hpp => call_data_record_image.hpp} | 12 ++-- .../grpc/call_data_set_record_status.hpp | 45 --------------- src/shisen_cpp/camera/node/camera_node.cpp | 11 ++-- .../grpc/call_data_get_capture_setting.cpp | 1 + .../grpc/call_data_get_record_status.cpp | 55 ------------------- ..._status.cpp => call_data_record_image.cpp} | 19 +++---- src/shisen_cpp/config/grpc/config.cpp | 6 +- 9 files changed, 24 insertions(+), 133 deletions(-) rename include/shisen_cpp/config/grpc/{call_data_get_record_status.hpp => call_data_record_image.hpp} (85%) delete mode 100644 include/shisen_cpp/config/grpc/call_data_set_record_status.hpp delete mode 100644 src/shisen_cpp/config/grpc/call_data_get_record_status.cpp rename src/shisen_cpp/config/grpc/{call_data_set_record_status.cpp => call_data_record_image.cpp} (71%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94a67fe..0ea8358 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,10 +38,9 @@ add_library(${PROJECT_NAME} SHARED "src/${PROJECT_NAME}/config/grpc/config.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_get_capture_setting.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_get_image.cpp" - "src/${PROJECT_NAME}/config/grpc/call_data_get_record_status.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_save_capture_setting.cpp" "src/${PROJECT_NAME}/config/grpc/call_data_set_capture_setting.cpp" - "src/${PROJECT_NAME}/config/grpc/call_data_set_record_status.cpp" + "src/${PROJECT_NAME}/config/grpc/call_data_record_image.cpp" "src/${PROJECT_NAME}/utility/capture_setting.cpp" "src/${PROJECT_NAME}/utility/interface.cpp" "src/${PROJECT_NAME}/node/shisen_cpp_node.cpp" diff --git a/include/shisen_cpp/camera/node/camera_node.hpp b/include/shisen_cpp/camera/node/camera_node.hpp index d0a5b9e..9f51ab5 100644 --- a/include/shisen_cpp/camera/node/camera_node.hpp +++ b/include/shisen_cpp/camera/node/camera_node.hpp @@ -58,9 +58,6 @@ class CameraNode std::shared_ptr image_provider; std::shared_ptr camera_config_provider; - bool get_record_status() { return is_record_on; } - void set_record_status(bool status) { is_record_on = status; } - private: rclcpp::Node::SharedPtr node; CaptureSetting current_capture_setting; @@ -72,8 +69,6 @@ class CameraNode rclcpp::Service::SharedPtr configure_capture_setting_service; Options options; - - bool is_record_on; }; } // namespace shisen_cpp::camera diff --git a/include/shisen_cpp/config/grpc/call_data_get_record_status.hpp b/include/shisen_cpp/config/grpc/call_data_record_image.hpp similarity index 85% rename from include/shisen_cpp/config/grpc/call_data_get_record_status.hpp rename to include/shisen_cpp/config/grpc/call_data_record_image.hpp index 506b8c1..dde27cc 100644 --- a/include/shisen_cpp/config/grpc/call_data_get_record_status.hpp +++ b/include/shisen_cpp/config/grpc/call_data_record_image.hpp @@ -18,19 +18,19 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#ifndef SHISEN_CPP__CONFIG__GRPC__CALL_DATA_GET_RECORD_STATUS_HPP__ -#define SHISEN_CPP__CONFIG__GRPC__CALL_DATA_GET_RECORD_STATUS_HPP__ +#ifndef SHISEN_CPP__CONFIG__GRPC__CALL_DATA_RECORD_IMAGE_HPP__ +#define SHISEN_CPP__CONFIG__GRPC__CALL_DATA_RECORD_IMAGE_HPP__ #include #include namespace shisen_cpp { -class CallDataGetRecordStatus -: CallData +class CallDataRecordImage +: CallData { public: - CallDataGetRecordStatus( + CallDataRecordImage( shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, const std::string & path, const std::shared_ptr& camera_node); @@ -42,4 +42,4 @@ class CallDataGetRecordStatus }; } // namespace shisen_cpp -#endif // SHISEN_CPP__CONFIG__GRPC__CALL_DATA_GET_RECORD_STATUS_HPP__ +#endif // SHISEN_CPP__CONFIG__GRPC__CALL_DATA_RECORD_IMAGE_HPP__ diff --git a/include/shisen_cpp/config/grpc/call_data_set_record_status.hpp b/include/shisen_cpp/config/grpc/call_data_set_record_status.hpp deleted file mode 100644 index 7087714..0000000 --- a/include/shisen_cpp/config/grpc/call_data_set_record_status.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2024 ICHIRO ITS -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#ifndef SHISEN_CPP__CONFIG__GRPC__CALL_DATA_SET_RECORD_STATUS_HPP__ -#define SHISEN_CPP__CONFIG__GRPC__CALL_DATA_SET_RECORD_STATUS_HPP__ - -#include -#include - -namespace shisen_cpp -{ -class CallDataSetRecordStatus -: CallData -{ -public: - CallDataSetRecordStatus( - shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, - const std::string & path, const std::shared_ptr& camera_node); - -protected: - void AddNextToCompletionQueue() override; - void WaitForRequest() override; - void HandleRequest() override; - std::shared_ptr camera_node_; -}; -} // namespace shisen_cpp - -#endif // SHISEN_CPP__CONFIG__GRPC__CALL_DATA_SET_RECORD_STATUS_HPP__ diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index 64a4786..8e2ac9e 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -34,7 +34,7 @@ namespace shisen_cpp::camera { CameraNode::CameraNode(rclcpp::Node::SharedPtr node, const Options & options) -: node(node), options(options), is_record_on(false) +: node(node), options(options) { } @@ -53,9 +53,6 @@ void CameraNode::update() if (!captured_mat.empty()) { on_mat_captured(captured_mat); on_camera_config(captured_mat.cols, captured_mat.rows); - if (is_record_on) { - save_image(captured_mat); - } } else { RCLCPP_WARN_ONCE(node->get_logger(), "Once, captured an empty mat!"); } @@ -75,10 +72,12 @@ void CameraNode::on_camera_config(int width, int height) void CameraNode::save_image(cv::Mat mat) { auto now = std::chrono::system_clock::now(); - std::time_t now_time = std::chrono::system_clock::to_time_t(now); + std::time_t now_time_t = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; std::stringstream ss; - ss << std::put_time(std::localtime(&now_time), "%Y-%m-%d_%H-%M-%S"); + ss << std::put_time(std::localtime(&now_time_t), "%Y-%m-%d_%H-%M-%S"); + ss << '-' << std::setfill('0') << std::setw(3) << now_ms.count(); std::string timestamp = ss.str(); std::string filename = "image/" + timestamp + ".jpg"; diff --git a/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp b/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp index bfedc23..fd42b85 100644 --- a/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp +++ b/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include diff --git a/src/shisen_cpp/config/grpc/call_data_get_record_status.cpp b/src/shisen_cpp/config/grpc/call_data_get_record_status.cpp deleted file mode 100644 index 71ee365..0000000 --- a/src/shisen_cpp/config/grpc/call_data_get_record_status.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2024 ICHIRO ITS -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#include -#include -#include -#include - -namespace shisen_cpp -{ -CallDataGetRecordStatus::CallDataGetRecordStatus( - shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, - const std::string & path, const std::shared_ptr& camera_node) -: CallData(service, cq, path), camera_node_(camera_node) -{ - Proceed(); -} - -void CallDataGetRecordStatus::AddNextToCompletionQueue() -{ - new CallDataGetRecordStatus(service_, cq_, path_, camera_node_); -} - -void CallDataGetRecordStatus::WaitForRequest() -{ - service_->RequestGetRecordStatus(&ctx_, &request_, &responder_, cq_, cq_, this); -} - -void CallDataGetRecordStatus::HandleRequest() -{ - try { - reply_.set_record(camera_node_->get_record_status()); - RCLCPP_INFO(rclcpp::get_logger("Get record status"), "status has been sent!"); - } catch(const std::exception& e) { - RCLCPP_ERROR(rclcpp::get_logger("Get Record Status"), e.what()); - } -} -} // namespace shisen_cpp diff --git a/src/shisen_cpp/config/grpc/call_data_set_record_status.cpp b/src/shisen_cpp/config/grpc/call_data_record_image.cpp similarity index 71% rename from src/shisen_cpp/config/grpc/call_data_set_record_status.cpp rename to src/shisen_cpp/config/grpc/call_data_record_image.cpp index aa000e9..11212f3 100644 --- a/src/shisen_cpp/config/grpc/call_data_set_record_status.cpp +++ b/src/shisen_cpp/config/grpc/call_data_record_image.cpp @@ -19,13 +19,13 @@ // THE SOFTWARE. #include -#include +#include #include #include namespace shisen_cpp { -CallDataSetRecordStatus::CallDataSetRecordStatus( +CallDataRecordImage::CallDataRecordImage( shisen_interfaces::proto::Config::AsyncService * service, grpc::ServerCompletionQueue * cq, const std::string & path, const std::shared_ptr& camera_node) : CallData(service, cq, path), camera_node_(camera_node) @@ -33,23 +33,22 @@ CallDataSetRecordStatus::CallDataSetRecordStatus( Proceed(); } -void CallDataSetRecordStatus::AddNextToCompletionQueue() +void CallDataRecordImage::AddNextToCompletionQueue() { - new CallDataSetRecordStatus(service_, cq_, path_, camera_node_); + new CallDataRecordImage(service_, cq_, path_, camera_node_); } -void CallDataSetRecordStatus::WaitForRequest() +void CallDataRecordImage::WaitForRequest() { - service_->RequestSetRecordStatus(&ctx_, &request_, &responder_, cq_, cq_, this); + service_->RequestRecordImage(&ctx_, &request_, &responder_, cq_, cq_, this); } -void CallDataSetRecordStatus::HandleRequest() +void CallDataRecordImage::HandleRequest() { try { - camera_node_->set_record_status(request_.record()); - RCLCPP_INFO(rclcpp::get_logger("Set record status"), "status has been apply!"); + camera_node_->save_image(camera_node_->get_mat()); } catch(const std::exception& e) { - RCLCPP_ERROR(rclcpp::get_logger("Set Record Status"), e.what()); + RCLCPP_ERROR(rclcpp::get_logger("Record Image"), e.what()); } } } // namespace shisen_cpp diff --git a/src/shisen_cpp/config/grpc/config.cpp b/src/shisen_cpp/config/grpc/config.cpp index 0baadf9..d6152e2 100644 --- a/src/shisen_cpp/config/grpc/config.cpp +++ b/src/shisen_cpp/config/grpc/config.cpp @@ -22,10 +22,9 @@ #include #include #include -#include #include #include -#include +#include #include #include @@ -74,8 +73,7 @@ void ConfigGrpc::Run(const std::string & path, std::shared_ptr Date: Tue, 2 Jul 2024 02:30:15 +0700 Subject: [PATCH 13/16] feat: create image dir if doesnt exist --- src/shisen_cpp/camera/node/camera_node.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index 8e2ac9e..b6cde7f 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include namespace shisen_cpp::camera { @@ -71,6 +73,15 @@ void CameraNode::on_camera_config(int width, int height) void CameraNode::save_image(cv::Mat mat) { + struct stat info; + + if (stat("image", &info) != 0) { + if (mkdir("image", 0777) == -1) { + RCLCPP_ERROR(node->get_logger(), "Error creating `image` directory!"); + return; + } + } + auto now = std::chrono::system_clock::now(); std::time_t now_time_t = std::chrono::system_clock::to_time_t(now); auto now_ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; From 10338bc2f42a87e4764416bf0854ef58ed128285 Mon Sep 17 00:00:00 2001 From: mbsaloka Date: Tue, 2 Jul 2024 02:42:58 +0700 Subject: [PATCH 14/16] fix: unintentional change --- src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp b/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp index fd42b85..bfedc23 100644 --- a/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp +++ b/src/shisen_cpp/config/grpc/call_data_get_capture_setting.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include #include From 752068fb3acbf9f053fa3e0dad8be7c748bcfd02 Mon Sep 17 00:00:00 2001 From: mbsaloka Date: Tue, 2 Jul 2024 10:15:45 +0700 Subject: [PATCH 15/16] fix: use std::filesystem --- src/shisen_cpp/camera/node/camera_node.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index b6cde7f..dd7668a 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -29,8 +29,6 @@ #include #include #include -#include -#include namespace shisen_cpp::camera { @@ -73,10 +71,8 @@ void CameraNode::on_camera_config(int width, int height) void CameraNode::save_image(cv::Mat mat) { - struct stat info; - - if (stat("image", &info) != 0) { - if (mkdir("image", 0777) == -1) { + if (!std::filesystem::exists("image")) { + if (!std::filesystem::create_directory("image")) { RCLCPP_ERROR(node->get_logger(), "Error creating `image` directory!"); return; } From 7c725277313b2b2106dad9f6cee345088c5d36c3 Mon Sep 17 00:00:00 2001 From: FaaizHaikal Date: Tue, 2 Jul 2024 19:08:53 +0700 Subject: [PATCH 16/16] feat: add init camera settings --- src/shisen_cpp/camera/node/camera_node.cpp | 2 -- src/shisen_cpp/camera/provider/image_provider.cpp | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/shisen_cpp/camera/node/camera_node.cpp b/src/shisen_cpp/camera/node/camera_node.cpp index dd7668a..99631f5 100644 --- a/src/shisen_cpp/camera/node/camera_node.cpp +++ b/src/shisen_cpp/camera/node/camera_node.cpp @@ -192,12 +192,10 @@ CaptureSetting CameraNode::on_configure_capture_setting( } if (new_capture_setting.temperature.is_not_empty()) { - video_capture->set(cv::CAP_PROP_AUTO_WB, 0); video_capture->set(cv::CAP_PROP_WB_TEMPERATURE, new_capture_setting.temperature); } if (new_capture_setting.exposure.is_not_empty()) { - video_capture->set(cv::CAP_PROP_AUTO_EXPOSURE, 1); video_capture->set(cv::CAP_PROP_EXPOSURE, new_capture_setting.exposure); } diff --git a/src/shisen_cpp/camera/provider/image_provider.cpp b/src/shisen_cpp/camera/provider/image_provider.cpp index 4bf82f5..e870733 100644 --- a/src/shisen_cpp/camera/provider/image_provider.cpp +++ b/src/shisen_cpp/camera/provider/image_provider.cpp @@ -38,6 +38,11 @@ ImageProvider::ImageProvider(const Options & options) video_capture->set(cv::CAP_PROP_FRAME_WIDTH, options.width); video_capture->set(cv::CAP_PROP_FRAME_HEIGHT, options.height); + video_capture->set(cv::CAP_PROP_AUTOFOCUS, 0); // Disable autofocus + video_capture->set(cv::CAP_PROP_AUTO_WB, 0); // Disable auto white balance + video_capture->set(cv::CAP_PROP_AUTO_EXPOSURE, 1); // Set auto exposure to manual mode + video_capture->set(cv::CAP_PROP_SHARPNESS, 0); // Set sharpness to 0 + video_capture->set(cv::CAP_PROP_FOCUS, 0); // Set focus to 0 } ImageProvider::~ImageProvider()