diff --git a/README.md b/README.md index 92e5623..6b92261 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,10 @@ This project is a migration from ROS1 to ROS2. The original code was developed b This project enables the conversion of a selected ROS2 topic of type `sensor_msgs::msg::Image` into an `RTSP` stream, with an anticipated delay of approximately 30-50ms. The generated stream can be utilized for various purposes such as remote control, object detection tasks, monitoring, and more. Please note that the migration process is ongoing, and therefore, the complete functionality of the original package is not yet available. The development is being carried out on Ubuntu 20.04 with ROS2 Foxy. + +You are reading now the README for a **default** ROS2 Foxy package. If you want to use this package written as a ROS2 Foxy component, checkout `ros2_component` branch. ## Dependencies -- ROS2 Foxy +- ROS2 foxy - gstreamer libs: ```bash @@ -19,10 +21,20 @@ sudo apt-get install libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1 mkdir -p ros2_ws/src cd ros2_ws/src/ ``` - - Clone the package: + - Clone the package and then navigate into the directory `image2rtsp`: ```bashrc - git clone https://github.com/45kmh/image2rtsp.git + git clone https://gitlab.rhrk.uni-kl.de/dmalad/image2rtsp.git + cd image2rtsp/ ``` + - To use the package as a **component** with ROS2 checkout **ros2_component** branch (Dont forget to switch the README). + ```bashrc + git checkout ros2_component + ``` + - To use the package as a **simple subscriber** with ROS2 Foxy stay on the `master` branch and follow the instructions. + - Check the framerate of the topic to be subscribed: + ```bashrc + ros2 topic hz /someTopic + ``` - Adjust `parameters.yaml` according to your needs: ```bashrc gedit ~/ros2_ws/src/image2rtsp/config/parameters.yaml @@ -31,16 +43,18 @@ sudo apt-get install libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1 topic: "/color/image_raw" # The ROS2 topic to subscribe to mountpoint: "/back" # Choose the mountpoint for the rtsp stream. # This will be able to be accessed from rtsp:///portAndMountpoint - caps: "video/x-raw,framerate=10/1,width=640,height=480" - # Set the caps to be applied after getting the ROS2 Image and before the x265 encoder. bitrate: "500" + framerate: "30" # Make sure that your framerate corresponds to the frequency of a topic you are subscribing to + caps_1: "video/x-raw,framerate=" + capr_2: "/1,width=640,height=480" + # Set the caps to be applied after getting the ROS2 Image and before the x265 encoder. Ignore + # framerate setting here. port: "8554" - local_only: True # True = rtsp://127.0.0.1:port (The stream is accessible only from the local machine) + local_only: True # True = rtsp://127.0.0.1:portAndMountpoint (The stream is accessible only from the local machine) # False = rtsp://0.0.0.0:portAndMountpoint (The stream is accessible from the outside) # For example, to access the stream running on the machine with IP = 192.168.20.20, # use rtsp://192.186.20.20:portAndMountpoint - # True = rtsp://127.0.0.1:portAndMountpoint (The stream is accessible only from the local machine) - - Save your configuration and navigate to `image2rtsp ` colcon root, source and build the package: + - Save your configuration and navigate to `ros2_ws` colcon root, source and build the package: ```bashrc cd ~/ros2_ws/ colcon build --packages-select image2rtsp diff --git a/config/parameters.yaml b/config/parameters.yaml index a5d9bac..0460e51 100644 --- a/config/parameters.yaml +++ b/config/parameters.yaml @@ -3,10 +3,11 @@ topic: "/color/image_raw" mountpoint: "/back" bitrate: "500" - caps: "video/x-raw,framerate=10/1,width=640,height=480" + framerate: "30" + caps_1: "video/x-raw, framerate =" + caps_2: "/1,width=640,height=480" port: "8554" - local_only: True # True = rtsp://127.0.0.1:port (The stream is accessible only from the local machine) + local_only: True # True = rtsp://127.0.0.1:portAndMountpoint (The stream is accessible only from the local machine) # False = rtsp://0.0.0.0:portAndMountpoint (The stream is accessible from the outside) # For example, to access the stream running on the machine with IP = 192.168.20.20, # use rtsp://192.186.20.20:portAndMountpoint - # True = rtsp://127.0.0.1:portAndMountpoint (The stream is accessible only from the local machine) \ No newline at end of file diff --git a/include/image2rtsp.hpp b/include/image2rtsp.hpp index 6f30dbf..122d085 100644 --- a/include/image2rtsp.hpp +++ b/include/image2rtsp.hpp @@ -18,7 +18,9 @@ private: string topic; string mountpoint; string bitrate; - string caps; + string framerate; + string caps_1; + string caps_2; string port; string pipeline; string pipeline_head; diff --git a/src/image2rtsp.cpp b/src/image2rtsp.cpp index 28bfc10..160eae0 100644 --- a/src/image2rtsp.cpp +++ b/src/image2rtsp.cpp @@ -12,19 +12,25 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){ this->declare_parameter("topic"); this->declare_parameter("mountpoint"); this->declare_parameter("bitrate"); - this->declare_parameter("caps"); + this->declare_parameter("framerate"); + this->declare_parameter("caps_1"); + this->declare_parameter("caps_2"); this->declare_parameter("port"); this->declare_parameter("local_only"); topic = this->get_parameter("topic").as_string(); mountpoint = this->get_parameter("mountpoint").as_string(); bitrate = this->get_parameter("bitrate").as_string(); - caps = this->get_parameter("caps").as_string(); + framerate = this->get_parameter("framerate").as_string(); + caps_1 = this->get_parameter("caps_1").as_string(); + caps_2 = this->get_parameter("caps_2").as_string(); port = this->get_parameter("port").as_string(); local_only = this->get_parameter("local_only").as_bool(); // Check if the parameter is set, since no default value is provided - if (!this->has_parameter("topic") || !this->has_parameter("mountpoint") || !this->has_parameter("bitrate") || !this->has_parameter("caps") || !this->has_parameter("port")){ + if (!this->has_parameter("topic") || !this->has_parameter("mountpoint") || !this->has_parameter("bitrate") || + !this->has_parameter("framerate") || !this->has_parameter("caps_1") || !this->has_parameter("caps_2") || + !this->has_parameter("port") || !this->has_parameter("local_only")){ rclcpp::shutdown(); // Shutdown the node if there are some issues with launch file return; } @@ -39,7 +45,7 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){ // Setup the pipeline pipeline_head = "( appsrc name=imagesrc do-timestamp=true min-latency=0 max-latency=0 max-bytes=1000 is-live=true ! videoconvert ! videoscale ! "; pipeline_tail = "key-int-max=30 ! video/x-h264, profile=baseline ! rtph264pay name=pay0 pt=96 )"; - pipeline = pipeline_head + caps + " ! x264enc tune=zerolatency bitrate=" + bitrate + pipeline_tail; + pipeline = pipeline_head + caps_1 + framerate + caps_2 + " ! x264enc tune=zerolatency bitrate=" + bitrate + pipeline_tail; rtsp_server_add_url(mountpoint.c_str(), pipeline.c_str(), (GstElement **)&(appsrc)); RCLCPP_INFO(this->get_logger(), "Stream available at rtsp://%s:%s%s", gst_rtsp_server_get_address(rtsp_server), port.c_str(), mountpoint.c_str()); } @@ -52,7 +58,7 @@ int main(int argc, char *argv[]){ rclcpp::spin(node); } }catch (const std::exception &e){ - RCLCPP_INFO(rclcpp::get_logger("image2rtsp"), "One or more required parameters are not set. Shutting down the node."); + RCLCPP_INFO(rclcpp::get_logger("image2rtsp"), "One or more required parameters are not set, or set incorrectly. Shutting down the node."); RCLCPP_INFO(rclcpp::get_logger("image2rtsp"), "Tip: Start the node only using launch file. Also rebuild after making changes in the YAML file"); RCLCPP_ERROR(rclcpp::get_logger("image2rtsp"), "Parameter is not set: %s", e.what()); } diff --git a/src/video.cpp b/src/video.cpp index 383c426..a91f452 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -131,7 +131,7 @@ GstCaps *Image2rtsp::gst_caps_new_from_image(const sensor_msgs::msg::Image::Shar "format", G_TYPE_STRING, format->second.c_str(), "width", G_TYPE_INT, msg->width, "height", G_TYPE_INT, msg->height, - "framerate", GST_TYPE_FRACTION, 10, 1, + "framerate", GST_TYPE_FRACTION, stoi(framerate), 1, nullptr); }