From c345d7d007ef98b858088f989e5c91d1c6120331 Mon Sep 17 00:00:00 2001 From: Victor Hogeweij Date: Thu, 30 Jan 2025 19:51:23 +0100 Subject: [PATCH 1/8] Remove the camera node in favor for v4l2_camera --- CMakeLists.txt | 10 -- README.md | 17 ++-- bindings/ros2/camera_node.cpp | 98 ------------------- bindings/ros2/face_detector_node.cpp | 2 +- .../usage_with_linux.md | 27 ++--- example/ROS_demo/face_detector_viewer.cpp | 2 +- package.xml | 1 + 7 files changed, 30 insertions(+), 127 deletions(-) delete mode 100644 bindings/ros2/camera_node.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index adf22ed..8ebc947 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,16 +136,6 @@ if (CLFML_ROS2_PACKAGE_BUILD) find_package(std_srvs REQUIRED) find_package(cv_bridge REQUIRED) target_link_libraries(${PROJECT_NAME} ${cv_bridge_LIBRARIES}) - add_executable(camera_node ${CMAKE_CURRENT_LIST_DIR}/bindings/ros2/camera_node.cpp) - ament_target_dependencies(camera_node - rclcpp - sensor_msgs - cv_bridge - std_msgs - geometry_msgs - std_srvs - OpenCV - ) add_executable(face_detector_node ${CMAKE_CURRENT_LIST_DIR}/bindings/ros2/face_detector_node.cpp) ament_target_dependencies(face_detector_node rclcpp diff --git a/README.md b/README.md index d2c4d5e..26a9ece 100644 --- a/README.md +++ b/README.md @@ -153,31 +153,36 @@ git clone https://github.com/CLFML/Face_Detector.Cpp.git source /opt/ros/jazzy/setup.bash ``` -3. Build the package: +3. Install the dependencies: +```bash +rosdep install --from-paths src -y --ignore-src +``` + +4. Build the package: ```bash colcon build --packages-select face_detector ``` -4. Set up the environment: +5. Set up the environment: ```bash source install/setup.bash ``` -5. Run the camera node: +6. Run the camera node: ```bash -ros2 run face_detector camera_node +ros2 run v4l2_camera v4l2_camera_node ``` -6. In another terminal, run the face detector node (don’t forget to source the setup script): +7. In another terminal, run the face detector node (don’t forget to source the setup script): ```bash ros2 run face_detector face_detector_node ``` -7. In yet another terminal, run the viewer: +8. In yet another terminal, run the viewer: ```bash ros2 run face_detector face_detector_viewer diff --git a/bindings/ros2/camera_node.cpp b/bindings/ros2/camera_node.cpp deleted file mode 100644 index 35ffdfe..0000000 --- a/bindings/ros2/camera_node.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -* Copyright 2024 (C) Richard Kroesen , Jeroen Veen & Victor Hogeweij -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* This file is part of the Face_Detector.Cpp library -* -* Author: Jeroen Veen -* -*/ -#include "rclcpp/rclcpp.hpp" -#include "sensor_msgs/msg/image.hpp" -#include -#include - -class CameraNode : public rclcpp::Node -{ -public: - CameraNode() : Node("camera_node") - { - declare_and_get_parameters(); - initialize_camera(); - - publisher_ = this->create_publisher("~/image_raw", 10); - - timer_ = this->create_wall_timer( - std::chrono::milliseconds(static_cast(1000.0 / camera_fps_)), - std::bind(&CameraNode::timer_callback, this)); - } - -private: - void declare_and_get_parameters() - { - declare_parameter("camera_index", 0); - declare_parameter("camera_fps", 30); - declare_parameter("camera_width", 640); - declare_parameter("camera_height", 480); - - camera_index_ = get_parameter("camera_index").as_int(); - camera_fps_ = get_parameter("camera_fps").as_int(); - camera_width_ = get_parameter("camera_width").as_int(); - camera_height_ = get_parameter("camera_height").as_int(); - } - - void initialize_camera() - { - cam_ = cv::VideoCapture(camera_index_, cv::CAP_V4L2); - if (!cam_.isOpened()) - { - RCLCPP_ERROR(this->get_logger(), "ERROR: Cannot open camera!"); - rclcpp::shutdown(); - return; - } - cam_.set(cv::CAP_PROP_FRAME_WIDTH, camera_width_); - cam_.set(cv::CAP_PROP_FRAME_HEIGHT, camera_height_); - cam_.set(cv::CAP_PROP_FPS, camera_fps_); - } - - void timer_callback() - { - cv::Mat frame; - if (cam_.read(frame)) - { - sensor_msgs::msg::Image::SharedPtr msg = cv_bridge::CvImage(std_msgs::msg::Header(), "bgr8", frame).toImageMsg(); - publisher_->publish(*msg); - } - else - { - RCLCPP_WARN(this->get_logger(), "Failed to capture frame, retrying..."); - } - } - - rclcpp::TimerBase::SharedPtr timer_; - rclcpp::Publisher::SharedPtr publisher_; - cv::VideoCapture cam_; - int camera_index_; - int camera_fps_; - int camera_width_; - int camera_height_; -}; - -int main(int argc, char * argv[]) -{ - rclcpp::init(argc, argv); - rclcpp::spin(std::make_shared()); - rclcpp::shutdown(); - return 0; -} \ No newline at end of file diff --git a/bindings/ros2/face_detector_node.cpp b/bindings/ros2/face_detector_node.cpp index aa46eeb..6623891 100644 --- a/bindings/ros2/face_detector_node.cpp +++ b/bindings/ros2/face_detector_node.cpp @@ -42,7 +42,7 @@ class FaceDetectorNode : public rclcpp::Node private: void declare_and_get_parameters() { - declare_parameter("camera_topic", "/camera_node/image_raw"); + declare_parameter("camera_topic", "/image_raw"); declare_parameter("face_detected_topic", "/face_detected"); declare_parameter("face_roi_topic", "/face_roi"); declare_parameter("face_landmarks_topic", "/face_landmarks"); diff --git a/docs/usage/ros2_build_environment/usage_with_linux.md b/docs/usage/ros2_build_environment/usage_with_linux.md index 2e3ce55..b20a0cf 100644 --- a/docs/usage/ros2_build_environment/usage_with_linux.md +++ b/docs/usage/ros2_build_environment/usage_with_linux.md @@ -34,38 +34,43 @@ git clone https://github.com/CLFML/Face_Detector.Cpp.git 2. Open the cloned repo folder in a terminal -Build the package with more verbose output +3. Source your ROS2 installation: ```bash -colcon build --event-handlers console_direct+ --packages-select face_detector +source /opt/ros/jazzy/setup.bash ``` -Note that, whenever build errors occur, and you need to clean the build, use +4. Install the ros2 dependencies: +```bash +rosdep install --from-paths src -y --ignore-src +``` + +5. Build the package with more verbose output ```bash -rm -rf build install log -rm -rf ~/.ros +colcon build --event-handlers console_direct+ --packages-select face_detector ``` -3. Source your ROS2 installation: +Note that, whenever build errors occur, and you need to clean the build, use ```bash -source /opt/ros/jazzy/setup.bash +rm -rf build install log +rm -rf ~/.ros ``` -4. Set up the environment +6. Set up the environment ```bash source install/setup.bash ``` -5. With the environment sourced, we can run executables built by colcon. Let’s run the camera node from the examples: +7. With the environment sourced, we can run executables built by colcon. Let’s run the camera node from the examples: ```bash -ros2 run face_detector camera_node +ros2 run v4l2_camera v4l2_camera_node ``` -5. In another terminal, let’s run the face detector node (don’t forget to source the setup script):6 +8. In another terminal, let’s run the face detector node (don’t forget to source the setup script):6 ```bash ros2 run face_detector face_detector_node ``` diff --git a/example/ROS_demo/face_detector_viewer.cpp b/example/ROS_demo/face_detector_viewer.cpp index a4f59ba..fc358e8 100644 --- a/example/ROS_demo/face_detector_viewer.cpp +++ b/example/ROS_demo/face_detector_viewer.cpp @@ -32,7 +32,7 @@ class FaceDetectorViewer : public rclcpp::Node FaceDetectorViewer() : Node("face_detector_viewer") { // Declare parameters for topic names - this->declare_parameter("camera_topic", "/camera_node/image_raw"); + this->declare_parameter("camera_topic", "/image_raw"); this->declare_parameter("face_detected_topic", "/face_detected"); this->declare_parameter("face_roi_topic", "/face_roi"); this->declare_parameter("face_landmarks_topic", "/face_landmarks"); diff --git a/package.xml b/package.xml index ce69d94..6ba98ce 100644 --- a/package.xml +++ b/package.xml @@ -20,6 +20,7 @@ std_msgs geometry_msgs std_srvs + v4l2_camera ament_lint_auto ament_lint_common From 8fbbae63e76113d88c020fafd09b38e6aee2ffa9 Mon Sep 17 00:00:00 2001 From: Victor Hogeweij Date: Thu, 30 Jan 2025 19:56:46 +0100 Subject: [PATCH 2/8] camera node was not fully removed from CMakeLists.txt --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ebc947..7bf7f48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,10 +146,8 @@ if (CLFML_ROS2_PACKAGE_BUILD) std_srvs OpenCV ) - target_link_libraries(camera_node face_detector) target_link_libraries(face_detector_node face_detector) install(TARGETS - camera_node face_detector_node DESTINATION lib/${PROJECT_NAME}) endif() From bdb3925b9002f72aaef670ed7bca5674a649f4ca Mon Sep 17 00:00:00 2001 From: Victor Hogeweij Date: Thu, 30 Jan 2025 19:58:38 +0100 Subject: [PATCH 3/8] remove todo line from readme for removal custom ros2 node --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 26a9ece..a11d38f 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,6 @@ See our [wiki](https://clfml.github.io/Face_Detector.Cpp/)... - Add support for MakeFiles and Bazel - Add Unit-tests - Add ROS2 package TPU support -- Drop custom ROS2 camera node and use a generic node, such as v4l2_camera or christianrauch/camera_ros - If needed to crunch ROS2 latency: Do not use nodes, put plugins in a container From 628ac5f901118736d2cc0d633bda7daa6e773294 Mon Sep 17 00:00:00 2001 From: Victor Hogeweij Date: Thu, 30 Jan 2025 20:14:22 +0100 Subject: [PATCH 4/8] add github workflows for ros2 ci/cd --- .github/workflows/ros2_code_compiles.yml | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/ros2_code_compiles.yml diff --git a/.github/workflows/ros2_code_compiles.yml b/.github/workflows/ros2_code_compiles.yml new file mode 100644 index 0000000..85f5360 --- /dev/null +++ b/.github/workflows/ros2_code_compiles.yml @@ -0,0 +1,38 @@ +name: code_compiles + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + workflow_dispatch: {} + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. + # You can convert this to a matrix build if you need cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-24.04 + + steps: + - uses: ros-tooling/setup-ros@v0.7 + with: + required-ros-distributions: jazzy + - uses: actions/checkout@v3 + + - name: Install prerequired packages + # To compile and run the code we require cmake, ninja and opencv + run: sudo apt-get update && sudo apt-get install build-essential cmake ninja-build libopencv-dev + + - name: Install dependencies + working-directory: ${{ github.workspace }} + run: | + sudo rosdep init || true + rosdep update + rosdep install --from-paths src -y --ignore-src + + - name: Colcon build + working-directory: ${{ github.workspace }} + run: | + source /opt/ros/jazzy/setup.bash + colcon build --packages-select face_detector From 19713f30c12a4037be29f53cf33ff018943445f9 Mon Sep 17 00:00:00 2001 From: Victor Hogeweij Date: Thu, 30 Jan 2025 20:15:34 +0100 Subject: [PATCH 5/8] change the ros2 workflow name --- .github/workflows/ros2_code_compiles.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ros2_code_compiles.yml b/.github/workflows/ros2_code_compiles.yml index 85f5360..431ab04 100644 --- a/.github/workflows/ros2_code_compiles.yml +++ b/.github/workflows/ros2_code_compiles.yml @@ -1,4 +1,4 @@ -name: code_compiles +name: ros_code_compiles on: push: From 0764b1a216bb0dfccfc23448981b1d942908d731 Mon Sep 17 00:00:00 2001 From: Victor Hogeweij Date: Thu, 30 Jan 2025 20:22:49 +0100 Subject: [PATCH 6/8] workflow didn't execute the build commands --- .github/workflows/ros2_code_compiles.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ros2_code_compiles.yml b/.github/workflows/ros2_code_compiles.yml index 431ab04..b0ce685 100644 --- a/.github/workflows/ros2_code_compiles.yml +++ b/.github/workflows/ros2_code_compiles.yml @@ -15,10 +15,10 @@ jobs: runs-on: ubuntu-24.04 steps: + - uses: actions/checkout@v3 - uses: ros-tooling/setup-ros@v0.7 with: required-ros-distributions: jazzy - - uses: actions/checkout@v3 - name: Install prerequired packages # To compile and run the code we require cmake, ninja and opencv From 71fa467431815a131c8c240e51be5d72675b0194 Mon Sep 17 00:00:00 2001 From: Victor Hogeweij Date: Fri, 31 Jan 2025 23:33:37 +0100 Subject: [PATCH 7/8] remove debug statement --- bindings/ros2/face_detector_node.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bindings/ros2/face_detector_node.cpp b/bindings/ros2/face_detector_node.cpp index 6623891..12bbb73 100644 --- a/bindings/ros2/face_detector_node.cpp +++ b/bindings/ros2/face_detector_node.cpp @@ -95,9 +95,6 @@ class FaceDetectorNode : public rclcpp::Node std_msgs::msg::Int32 face_detected_msg = std_msgs::msg::Int32(); face_detected_msg.data = det_.detected() + 1; // +1 because detector returns -1 for no face and 0 for face detected! face_detected_pub_->publish(face_detected_msg); - - if (face_detected_msg.data) - RCLCPP_INFO(get_logger(), "face detected"); } void publish_face_roi() @@ -154,4 +151,4 @@ int main(int argc, char** argv) rclcpp::spin(std::make_shared()); rclcpp::shutdown(); return 0; -} \ No newline at end of file +} From 4d6c96e1a12d1911028ea5c50e909db25cb74c0f Mon Sep 17 00:00:00 2001 From: Victor Hogeweij Date: Fri, 31 Jan 2025 23:55:39 +0100 Subject: [PATCH 8/8] add small improvement to script that uses current workindirectory using pwd --- bindings/ros2/set_ld_path.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/ros2/set_ld_path.sh b/bindings/ros2/set_ld_path.sh index 7c072da..93371e6 100755 --- a/bindings/ros2/set_ld_path.sh +++ b/bindings/ros2/set_ld_path.sh @@ -7,7 +7,7 @@ if [ ! -d "install" ]; then fi # Path to the dynamic library -LIB_PATH="install/face_detector/lib/face_detector/libtensorflowlite.so" +LIB_PATH="$(pwd)/install/face_detector/lib/face_detector/libtensorflowlite.so" # Check if the dynamic library exists if [ -f "$LIB_PATH" ]; then