ros2 component stable version

This commit is contained in:
dmalad 2023-12-04 16:37:58 +01:00
parent 083693732c
commit 59baa89f5d
12 changed files with 170 additions and 145 deletions

54
CMakeLists.txt Normal file → Executable file
View File

@ -18,36 +18,65 @@ endif()
# find dependencies # find dependencies
find_package(ament_cmake REQUIRED) find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED) find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(sensor_msgs REQUIRED) find_package(sensor_msgs REQUIRED)
find_package(rcutils REQUIRED)
pkg_check_modules(GST REQUIRED pkg_check_modules(GST REQUIRED
gstreamer-1.0 gstreamer-1.0
gstreamer-app-1.0 gstreamer-app-1.0
gstreamer-rtsp-server-1.0 gstreamer-rtsp-server-1.0
) )
file(GLOB SOURCES src/video.cpp)
add_executable(image2rtsp src/image2rtsp.cpp ${SOURCES}) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
ament_target_dependencies(image2rtsp rclcpp sensor_msgs)
include_directories( include_directories(
include
${GST_INCLUDE_DIRS} ${GST_INCLUDE_DIRS}
) )
# create ament index resource which references the libraries in the binary dir
set(node_plugins "")
add_library(image2rtsp SHARED
src/image2rtsp.cpp src/video.cpp)
ament_target_dependencies(image2rtsp rclcpp sensor_msgs)
target_compile_definitions(image2rtsp
PRIVATE "IMAGE2RTSP_BUILDING_DLL")
target_link_libraries(image2rtsp target_link_libraries(image2rtsp
${GST_LIBRARIES} ${sensor_msgs_TARGETS}
) ${GST_LIBRARIES})
ament_target_dependencies(image2rtsp
"rclcpp"
"rclcpp_components"
"sensor_msgs")
rclcpp_components_register_nodes(image2rtsp "Image2rtsp")
set(node_plugins "${node_plugins}Image2rtsp;$<TARGET_FILE:image2rtsp>\n")
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# uncomment the line when a copyright and license is not present in all source files
#set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# uncomment the line when this package is not in a git repo
#set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
install(TARGETS install(TARGETS
image2rtsp image2rtsp
DESTINATION lib/${PROJECT_NAME} ARCHIVE DESTINATION lib
) LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
install( install(DIRECTORY
DIRECTORY
config
launch launch
DESTINATION share/${PROJECT_NAME} DESTINATION share/${PROJECT_NAME}
) )
# Install Python modules # Install Python modules
ament_python_install_package(python) ament_python_install_package(python)
@ -57,5 +86,4 @@ install(PROGRAMS
DESTINATION lib/${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME}
) )
ament_package() ament_package()

11
LICENSE
View File

@ -1,11 +0,0 @@
Copyright <2023> <Dzmitry Maladzenkau>
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -5,8 +5,11 @@ 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. 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. The development is being carried out on Ubuntu 20.04 with ROS2 Foxy.
You are reading now the README for a package written as a ROS2 Foxy **component**. If you want to use this package as a default ROS2 Foxy package, checkout `master` branch.
## Dependencies ## Dependencies
- ROS2 Foxy - ROS2 foxy
- gstreamer libs: - gstreamer libs:
```bash ```bash
@ -19,46 +22,65 @@ sudo apt-get install libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1
mkdir -p ros2_ws/src mkdir -p ros2_ws/src
cd ros2_ws/src/ cd ros2_ws/src/
``` ```
- Clone the package: - Clone the package and navigate into the directory `image2rtsp`:
```bashrc ```bashrc
git clone https://github.com/45kmh/image2rtsp.git git clone https://gitlab.rhrk.uni-kl.de/dmalad/image2rtsp.git
cd image2rtsp/
``` ```
- Adjust `parameters.yaml` according to your needs: - To use the package as a **simple subscriber** with ROS2 Foxy stay on the main (Dont forget to switch the README).
- To use the package as a **component** with ROS2 checkout **ros2_component** branch.
```bashrc ```bashrc
gedit ~/ros2_ws/src/image2rtsp/config/parameters.yaml git checkout ros2_component
```
- Check the framerate of the topic to be subscribed:
```bashrc
ros2 topic hz /someTopic
```
- All the parameters are hardcoded in `image2rtsp.hpp`, so be sure to change them before adding the `Image2rtsp` component into `ComponentManager`:
```bashrc
gedit ~/ros2_ws/src/image2rtsp/include/image2rtsp.hpp
``` ```
# Example ROS2 Image topic stream # Example ROS2 Image topic stream
topic: "/color/image_raw" # The ROS2 topic to subscribe to topic: "/color/image_raw" # The ROS2 topic to subscribe to
mountpoint: "/back" # Choose the mountpoint for the rtsp stream. mountpoint: "rs" # Choose the mountpoint for the rtsp stream.
# This will be able to be accessed from rtsp://<server_ip>/portAndMountpoint # This will be able to be accessed from rtsp://<server_ip>/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" bitrate: "500"
framerate = "30";
caps: "video/x-raw,framerate=" + framerate + "/1,width=1280,height=720";
# Set the caps to be applied after getting the ROS2 Image and before the x265 encoder.
port: "8554" 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:port (The stream is accessible only from the local machine)
# False = rtsp://0.0.0.0:portAndMountpoint (The stream is accessible from the outside) # 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, # For example, to access the stream running on the machine with IP = 192.168.20.20,
# use rtsp://192.186.20.20:portAndMountpoint # 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 `ros2_ws` colcon root, source and build the package:
- Save your configuration and navigate to `image2rtsp ` colcon root, source and build the package:
```bashrc ```bashrc
cd ~/ros2_ws/ cd ~/ros2_ws/
colcon build --packages-select image2rtsp colcon build --packages-select image2rtsp
``` ```
## Run ## Run
- Source `install` and launch the package: - Open another shell, source local setup and run `ComponentManager`:
```bashrc
cd ~/ros2_ws/
source install/setup.bash
ros2 run rclcpp_components component_container
```
- Add a component with a publisher node first.
- Source `install` and add the `Image2rtsp` component:
```bashrc ```bashrc
source install/setup.bash source install/setup.bash
ros2 launch image2rtsp image2rtsp.launch.py ros2 component load /ComponentManager image2rtsp Image2rtsp
```
OR to enable intra-process communication:
```bashrc
ros2 component load /ComponentManager image2rtsp Image2rtsp -e use_intra_process_comms:=true
``` ```
Don't use **`ros2 run`**!
## Check the stream ## Check the stream
To check the stream, follow the instructions for gstreamer, mpv or VLC provided by [CircusMonkey](https://github.com/CircusMonkey/ros_rtsp/blob/master/README.md) or use python script provided in this package (ensure before that the open-cv library is installed, if not `pip install opencv-python`). Open new terminal, ensure that the topic to be converted exists and the RTSP stream is running. Then: To check the stream, follow the instructions for gstreamer, mpv or VLC provided by [CircusMonkey](https://github.com/CircusMonkey/ros_rtsp/blob/master/README.md) or use python script provided in this package (ensure before that the open-cv library is installed, if not `pip install opencv-python`). Ensure that components with publisher and subscriber nodes are loaded in the `ComponentManager`. Then:
```bash ```bash
gedit ~/ros2_ws/src/image2rtsp/python/rtsp.py gedit ~/ros2_ws/src/image2rtsp/python/rtsp.py
``` ```
Replace the `rtsp://127.0.0.1:8554/back` with your server's IP address, port and mount point `rtsp://YOUR_IP:PORT/MOUNT_POINT`. Save and run: Replace the `rtsp://0.0.0.0:8554/rs` with your server's IP address, port and mount point `rtsp://YOUR_IP:PORT/MOUNT_POINT`. Save and run:
```bash ```bash
cd ~/ros2_ws/ cd ~/ros2_ws/
source install/setup.bash source install/setup.bash
@ -67,9 +89,7 @@ ros2 launch image2rtsp rtsp.launch.py
## Limitations ## Limitations
- As was previously mentioned, this package allows the conversion of only one topic into an RTSP Stream. - As was previously mentioned, this package allows the conversion of only one topic into an RTSP Stream.
- Some machines may have a significantly bigger delay of about 150-200ms. The reason is currently unknown. - Some machines may have a significantly bigger delay of about 150-200ms. The reason is currently unknown.
- Its possible to use this package with Humble if ROS2 parameters are hardcoded as variables.
## To Do ## To Do
- Add a branch with the package rewritten as a ROS2 component
- Port the package to Nvidia Jetson Orin. Will the use of the Nvidia encoder make the delay smaller? - Port the package to Nvidia Jetson Orin. Will the use of the Nvidia encoder make the delay smaller?
- Port packages to ROS2 Humble. - Port packages to ROS2 Humble.
- Complete the functionality according to the functionality of the original ROS package. - Complete the functionality according to the functionality of the original ROS package.

View File

@ -1,12 +0,0 @@
/image2rtsp:
ros__parameters:
topic: "/color/image_raw"
mountpoint: "/back"
bitrate: "500"
caps: "video/x-raw,framerate=10/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)
# 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)

50
include/image2rtsp.hpp Normal file → Executable file
View File

@ -1,41 +1,47 @@
#ifndef IMAGE2RTSP_IMAGE2RTSP_HPP #ifndef IMAGE2RTSP__IMAGE2RTSP_HPP_
#define IMAGE2RTSP_IMAGE2RTSP_HPP #define IMAGE2RTSP__IMAGE2RTSP_HPP_
#include "visibility_control.h"
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h> #include <gst/rtsp-server/rtsp-server.h>
#include <rclcpp/rclcpp.hpp> #include <rclcpp/rclcpp.hpp>
#include <string> #include <string>
#include "sensor_msgs/msg/image.hpp" #include "sensor_msgs/msg/image.hpp"
#include <gst/app/gstappsrc.h>
using namespace std; using namespace std;
class Image2rtsp : public rclcpp::Node{ class Image2rtsp : public rclcpp::Node
{
public: public:
Image2rtsp(); IMAGE2RTSP_PUBLIC
GstRTSPServer *rtsp_server; explicit Image2rtsp(const rclcpp::NodeOptions & options);
GstRTSPServer *rtsp_server;
private: private:
string topic; string topic = "/color/image_raw";
string mountpoint; string mountpoint = "/rs";
string bitrate; string bitrate = "500";
string caps; string framerate = "30";
string port; string caps = "video/x-raw,framerate=" + framerate + "/1,width=1280,height=720";
string pipeline; string port = "8554";
string pipeline_head; string pipeline;
string pipeline_tail; string pipeline_head;
bool local_only; string pipeline_tail;
GstAppSrc *appsrc; bool local_only = false;
GstAppSrc *appsrc;
void video_mainloop_start(); void video_mainloop_start();
void rtsp_server_add_url(const char *url, const char *sPipeline, GstElement **appsrc); void rtsp_server_add_url(const char *url, const char *sPipeline, GstElement **appsrc);
void topic_callback(const sensor_msgs::msg::Image::SharedPtr msg); void topic_callback(const sensor_msgs::msg::Image::SharedPtr msg);
GstRTSPServer *rtsp_server_create(const string &port, const bool local_only); GstRTSPServer *rtsp_server_create(const string &port, const bool local_only);
GstCaps *gst_caps_new_from_image(const sensor_msgs::msg::Image::SharedPtr &msg); GstCaps *gst_caps_new_from_image(const sensor_msgs::msg::Image::SharedPtr &msg);
rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr subscription_; rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr subscription_;
}; };
static void media_configure(GstRTSPMediaFactory *factory, GstRTSPMedia *media, GstElement **appsrc); static void media_configure(GstRTSPMediaFactory *factory, GstRTSPMedia *media, GstElement **appsrc);
static void *mainloop(void *arg); static void *mainloop(void *arg);
static gboolean session_cleanup(Image2rtsp *node, rclcpp::Logger logger, gboolean ignored); static gboolean session_cleanup(Image2rtsp *node, rclcpp::Logger logger, gboolean ignored);
#endif // IMAGE2RTSP_IMAGE2RTSP_HPP
#endif // IMAGE2RTSP__IMAGE2RTSP_HPP_

44
include/visibility_control.h Executable file
View File

@ -0,0 +1,44 @@
#ifndef IMAGE2RTSP__VISIBILITY_CONTROL_H_
#define IMAGE2RTSP__VISIBILITY_CONTROL_H_
#ifdef __cplusplus
extern "C"
{
#endif
// This logic was borrowed (then namespaced) from the examples on the gcc wiki:
// https://gcc.gnu.org/wiki/Visibility
#if defined _WIN32 || defined __CYGWIN__
#ifdef __GNUC__
#define IMAGE2RTSP_EXPORT __attribute__ ((dllexport))
#define IMAGE2RTSP_IMPORT __attribute__ ((dllimport))
#else
#define IMAGE2RTSP_EXPORT __declspec(dllexport)
#define IMAGE2RTSP_IMPORT __declspec(dllimport)
#endif
#ifdef IMAGE2RTSP_BUILDING_DLL
#define IMAGE2RTSP_PUBLIC IMAGE2RTSP_EXPORT
#else
#define IMAGE2RTSP_PUBLIC IMAGE2RTSP_IMPORT
#endif
#define IMAGE2RTSP_PUBLIC_TYPE IMAGE2RTSP_PUBLIC
#define IMAGE2RTSP_LOCAL
#else
#define IMAGE2RTSP_EXPORT __attribute__ ((visibility("default")))
#define IMAGE2RTSP_IMPORT
#if __GNUC__ >= 4
#define IMAGE2RTSP_PUBLIC __attribute__ ((visibility("default")))
#define IMAGE2RTSP_LOCAL __attribute__ ((visibility("hidden")))
#else
#define IMAGE2RTSP_PUBLIC
#define IMAGE2RTSP_LOCAL
#endif
#define IMAGE2RTSP_PUBLIC_TYPE
#endif
#ifdef __cplusplus
}
#endif
#endif // IMAGE2RTSP__VISIBILITY_CONTROL_H_

View File

@ -1,20 +0,0 @@
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
config = os.path.join(
get_package_share_directory('image2rtsp'),
'config',
'parameters.yaml'
)
return LaunchDescription([
Node(
package='image2rtsp',
executable='image2rtsp',
name='image2rtsp',
parameters=[config]
)
])

View File

@ -1,10 +1,11 @@
from launch import LaunchDescription from launch import LaunchDescription
from launch.actions import ExecuteProcess from launch.actions import ExecuteProcess
from ament_index_python.packages import get_package_share_directory
import os import os
def generate_launch_description(): def generate_launch_description():
home_dir = os.path.expanduser("~") pkg_share = get_package_share_directory('image2rtsp')
script_path = os.path.join(home_dir, 'ros2_ws/src/image2rtsp/python/rtsp.py') script_path = os.path.join(pkg_share, '../../../../src/image2rtsp/python/rtsp.py')
return LaunchDescription( return LaunchDescription(
[ [

5
package.xml Normal file → Executable file
View File

@ -3,20 +3,19 @@
<package format="3"> <package format="3">
<name>image2rtsp</name> <name>image2rtsp</name>
<version>0.0.0</version> <version>0.0.0</version>
<description>topic to RTSP stream package</description> <description>takes ROS2 topics as a source and provides rtsp video stream as a sink</description>
<maintainer email="dmalad@rptu.de">dmitry</maintainer> <maintainer email="dmalad@rptu.de">dmitry</maintainer>
<license>BSD</license> <license>BSD</license>
<buildtool_depend>ament_cmake</buildtool_depend> <buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend> <depend>rclcpp</depend>
<depend>rclcpp_components</depend>
<depend>sensor_msgs</depend> <depend>sensor_msgs</depend>
<test_depend>ament_lint_auto</test_depend> <test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend> <test_depend>ament_lint_common</test_depend>
<exec_depend>ros2launch</exec_depend>
<export> <export>
<build_type>ament_cmake</build_type> <build_type>ament_cmake</build_type>
</export> </export>

View File

@ -1,6 +1,6 @@
import cv2 import cv2
cap = cv2.VideoCapture('rtsp://127.0.0.1:8554/back') cap = cv2.VideoCapture('rtsp://0.0.0.0:8554/rs')
while True: while True:
ret, frame = cap.read() ret, frame = cap.read()

44
src/image2rtsp.cpp Normal file → Executable file
View File

@ -1,34 +1,13 @@
#include "../include/image2rtsp.hpp"
#include "rclcpp/rclcpp.hpp" #include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/image.hpp" #include "sensor_msgs/msg/image.hpp"
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h> #include <gst/rtsp-server/rtsp-server.h>
#include <gst/app/gstappsrc.h> #include <gst/app/gstappsrc.h>
#include "../include/image2rtsp.hpp"
using std::placeholders::_1; using std::placeholders::_1;
Image2rtsp::Image2rtsp() : Node("image2rtsp"){ Image2rtsp::Image2rtsp(const rclcpp::NodeOptions & options) : Node("image2rtsp"){
// Declare and get the parameters
this->declare_parameter("topic");
this->declare_parameter("mountpoint");
this->declare_parameter("bitrate");
this->declare_parameter("caps");
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();
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")){
rclcpp::shutdown(); // Shutdown the node if there are some issues with launch file
return;
}
// Start the subscription // Start the subscription
subscription_ = this->create_subscription<sensor_msgs::msg::Image>(topic, 10, std::bind(&Image2rtsp::topic_callback, this, _1)); subscription_ = this->create_subscription<sensor_msgs::msg::Image>(topic, 10, std::bind(&Image2rtsp::topic_callback, this, _1));
@ -37,25 +16,12 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){
rtsp_server = rtsp_server_create(port, local_only); rtsp_server = rtsp_server_create(port, local_only);
appsrc = NULL; appsrc = NULL;
// Setup the pipeline // 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_head = "( appsrc name=imagesrc do-timestamp=true min-latency=0 max-latency=0 max-bytes=1000 is-live=true ! videoconvert ! ";
pipeline_tail = "key-int-max=30 ! video/x-h264, profile=baseline ! rtph264pay name=pay0 pt=96 )"; 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 + " ! x264enc tune=zerolatency bitrate=" + bitrate + pipeline_tail;
rtsp_server_add_url(mountpoint.c_str(), pipeline.c_str(), (GstElement **)&(appsrc)); 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()); 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());
} }
int main(int argc, char *argv[]){ #include "rclcpp_components/register_node_macro.hpp"
rclcpp::init(argc, argv); RCLCPP_COMPONENTS_REGISTER_NODE(Image2rtsp)
try{
auto node = std::make_shared<Image2rtsp>();
if (rclcpp::ok()){
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"), "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());
}
rclcpp::shutdown();
return 0;
}

View File

@ -4,10 +4,14 @@
#include <rclcpp/rclcpp.hpp> #include <rclcpp/rclcpp.hpp>
#include "../include/image2rtsp.hpp" #include "../include/image2rtsp.hpp"
#include "../include/image_encodings.h"
extern "C" {
#include "../include/image_encodings.h"
}
using namespace std; using namespace std;
static void *mainloop(void *arg){ static void *mainloop(void *arg){
GMainLoop *loop = g_main_loop_new(NULL, FALSE); GMainLoop *loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop); g_main_loop_run(loop);
@ -131,7 +135,7 @@ GstCaps *Image2rtsp::gst_caps_new_from_image(const sensor_msgs::msg::Image::Shar
"format", G_TYPE_STRING, format->second.c_str(), "format", G_TYPE_STRING, format->second.c_str(),
"width", G_TYPE_INT, msg->width, "width", G_TYPE_INT, msg->width,
"height", G_TYPE_INT, msg->height, "height", G_TYPE_INT, msg->height,
"framerate", GST_TYPE_FRACTION, 10, 1, "framerate", GST_TYPE_FRACTION, stoi(framerate), 1,
nullptr); nullptr);
} }