Add Docker support and enhance logging for image processing

This commit is contained in:
Akash Shingha 2026-03-10 02:02:31 +02:00
parent a2a3adf08e
commit 09afdc5d3c
9 changed files with 125 additions and 0 deletions

6
.dockerignore Normal file
View File

@ -0,0 +1,6 @@
build
install
log
.git
*.pyc
__pycache__

2
.gitignore vendored
View File

@ -5,3 +5,5 @@ build/
# VSC stuff
.vscode
# Local python virtualenv
.venv/

41
Dockerfile Normal file
View File

@ -0,0 +1,41 @@
FROM ros:humble-ros-base AS build
SHELL ["/bin/bash", "-lc"]
WORKDIR /ws
# Install OS packages first (cached layer when requirements.txt unchanged)
COPY apt-requirements.txt /tmp/requirements.txt
RUN apt-get update \
&& xargs -a /tmp/requirements.txt apt-get install -y --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* /tmp/requirements.txt
# Copy package manifest(s) so rosdep can install system deps and this layer caches
COPY package.xml ./package.xml
RUN source /opt/ros/humble/setup.bash \
&& rosdep update || true \
&& rosdep install -i --from-paths . --rosdistro humble -y || true
# Copy rest of the sources after deps to avoid busting the deps layer on code changes
COPY . .
# Build with Ninja + ccache for faster incremental builds inside the container
RUN source /opt/ros/humble/setup.bash \
&& CCACHE_DIR=/ccache mkdir -p /ccache \
&& chmod 777 /ccache \
&& colcon build --parallel-workers $(nproc) \
--cmake-args -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
FROM ros:humble-ros-base
WORKDIR /ws
## Install minimal runtime packages required by the built binaries
COPY apt-runtime.txt /tmp/apt-runtime.txt
RUN apt-get update \
&& xargs -a /tmp/apt-runtime.txt apt-get install -y --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* /tmp/apt-runtime.txt
COPY --from=build /ws/install /ws/install
COPY docker-entrypoint.sh /ros_entrypoint.sh
RUN chmod +x /ros_entrypoint.sh
ENV ROS_DISTRO=humble
ENTRYPOINT ["/ros_entrypoint.sh"]
CMD ["image2rtsp.launch.py"]

18
apt-requirements.txt Normal file
View File

@ -0,0 +1,18 @@
python3-colcon-common-extensions
python3-pip
git
build-essential
cmake
pkg-config
libopencv-dev
python3-opencv
curl
python3-rosdep
python3-rosdistro
libgstreamer1.0-dev
libgstreamer-plugins-base1.0-dev
libgstreamer-plugins-good1.0-dev
libgstreamer-plugins-bad1.0-dev
libgstrtspserver-1.0-dev
ccache
ninja-build

10
apt-runtime.txt Normal file
View File

@ -0,0 +1,10 @@
libgstreamer1.0-0
gstreamer1.0-plugins-base
gstreamer1.0-plugins-good
gstreamer1.0-plugins-bad
gstreamer1.0-plugins-ugly
libgstrtspserver-1.0-0
python3-opencv
libopencv-dev
ros-humble-ros2cli
ros-humble-rclpy

31
docker-compose.yml Normal file
View File

@ -0,0 +1,31 @@
services:
image2rtsp:
build: .
image: image2rtsp:latest
# Use host networking so the container binds to the host interfaces directly
# (Linux only). Remove port mapping when using host networking.
network_mode: "host"
environment:
- ROS_DISTRO=humble
# Propagate host ROS environment so DDS/discovery match (set on host if needed)
- ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-0}
- RMW_IMPLEMENTATION=${RMW_IMPLEMENTATION:-}
# Ensure the node binds to non-localhost interface (disable local_only)
# and subscribe to the actual image topic available on the host
command: ["image2rtsp.launch.py", "local_only:=false", "topic:=/camera/image"]
# Optional: add a lightweight test publisher service if you want the container
# to publish dummy images for testing (uncomment and adjust image if required).
# test_publisher:
# image: image2rtsp:latest
# network_mode: "host"
# environment:
# - ROS_DISTRO=humble
# - ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-0}
# - RMW_IMPLEMENTATION=${RMW_IMPLEMENTATION:-}
# command: ["/bin/bash", "-c", "python3 - <<'PY'\nimport time, rclpy\nfrom rclpy.node import Node\nfrom sensor_msgs.msg import Image\nrclpy.init()\nnode = Node('dummy_pub')\npub = node.create_publisher(Image, '/camera/image', 10)\nmsg = Image()\nmsg.width=640; msg.height=480; msg.encoding='rgb8'; msg.is_bigendian=0; msg.step=msg.width*3\nmsg.data = bytes([0])*(msg.step*msg.height)\ntry:\n while rclpy.ok():\n pub.publish(msg)\n rclpy.spin_once(node, timeout_sec=0.01)\n time.sleep(1/30)\nexcept KeyboardInterrupt:\n pass\nrclpy.shutdown()\nPY"]
# Do not mount the workspace by default — the image contains the built overlay.
# To use a host workspace for live development, uncomment and adjust the line below:
# volumes:
# - ./:/ws:rw
restart: unless-stopped

15
docker-entrypoint.sh Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -e
# Source ROS and workspace overlays then exec ros2 launch with provided args
if [ -n "${ROS_DISTRO:-}" ]; then
source "/opt/ros/${ROS_DISTRO}/setup.bash" || true
else
source /opt/ros/humble/setup.bash || true
fi
if [ -f /ws/install/setup.bash ]; then
source /ws/install/setup.bash
fi
exec ros2 launch image2rtsp "$@"

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
opencv-python

View File

@ -159,6 +159,7 @@ void Image2rtsp::topic_callback(const sensor_msgs::msg::Image::SharedPtr msg){
GstCaps *caps; // image properties. see return of Image2rtsp::gst_caps_new_from_image
char *gst_type, *gst_format = (char *)"";
if (appsrc != NULL){
RCLCPP_INFO(this->get_logger(), "Received image %dx%d, encoding=%s", msg->width, msg->height, msg->encoding.c_str());
// Set caps from message
caps = gst_caps_new_from_image(msg);
gst_app_src_set_caps(appsrc, caps);