Skip to content

Commit

Permalink
Add Healthcheck (#17)
Browse files Browse the repository at this point in the history
* Add Healthcheck

* Update healthcheck.cpp

* Timeout

* New version of Healthcheck

* timeout + formatting

* Fix first healthcheck running

* Add entrypoint

* Delete debug msg

* refactor

* suggestions
  • Loading branch information
rafal-gorecki authored Nov 27, 2023
1 parent d638521 commit 8aa41f3
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Dockerfile.cpu
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ RUN echo $(cat /ros2_ws/src/zed_cpu/package.xml | grep '<version>' | sed -r 's/.

# Setup entrypoint
COPY ./ros_entrypoint.sh /
ENTRYPOINT ["/ros_entrypoint.sh"]
ENTRYPOINT ["/ros_entrypoint.sh"]
45 changes: 40 additions & 5 deletions Dockerfile.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ ARG ZED_SDK_MAJOR=4
ARG ZED_SDK_MINOR=0
ARG ROS_DISTRO=humble

### DOWNLOAD HUSARNET ###
FROM ubuntu:20.04 AS husarnet-dds-getter

ARG TARGETARCH
ARG HUSARNET_DDS_RELEASE="v1.3.5"

ENV HUSARNET_DDS_DEBUG=FALSE

RUN apt update && apt install -y \
curl

RUN curl -L https://github.com/husarnet/husarnet-dds/releases/download/${HUSARNET_DDS_RELEASE}/husarnet-dds-linux-${TARGETARCH} -o /usr/bin/husarnet-dds

### BUILD IMAGE ###
FROM nvidia/cuda:${CUDA_MAJOR}.${CUDA_MINOR}.${CUDA_PATCH}-devel-ubuntu${UBUNTU_RELEASE_YEAR}.04 AS build

Expand Down Expand Up @@ -36,12 +49,12 @@ RUN echo "Europe/Paris" > /etc/localtime ; echo "CUDA Version ${CUDA_MAJOR}.${CU
ln -sf /lib/x86_64-linux-gnu/libusb-1.0.so.0 /usr/lib/x86_64-linux-gnu/libusb-1.0.so && \
rm ZED_SDK_Linux_Ubuntu.run && \
rm -rf /var/lib/apt/lists/*

# ROS install
ENV ROS_DISTRO $ROS_DISTRO
RUN echo "deb http://packages.ros.org/ros2/ubuntu jammy main" > /etc/apt/sources.list.d/ros2-latest.list && \
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 && \
apt-get update && \
apt-get update && \
apt-get install -y --no-install-recommends \
ros-$ROS_DISTRO-ros-core \
&& rm -rf /var/lib/apt/lists/*
Expand Down Expand Up @@ -76,6 +89,18 @@ RUN apt-get update && \
rosdep install --from-paths src -y -i && \
rm -rf /var/lib/apt/lists/*

# Create health check package
RUN cd src/ && \
source /opt/ros/$ROS_DISTRO/setup.bash && \
ros2 pkg create healthcheck_pkg --build-type ament_cmake --dependencies rclcpp sensor_msgs && \
sed -i '/find_package(sensor_msgs REQUIRED)/a \
add_executable(healthcheck_node src/healthcheck.cpp)\n \
ament_target_dependencies(healthcheck_node rclcpp sensor_msgs)\n \
install(TARGETS healthcheck_node DESTINATION lib/${PROJECT_NAME})' \
/ros2_ws/src/healthcheck_pkg/CMakeLists.txt

COPY ./healthcheck.cpp /ros2_ws/src/healthcheck_pkg/src/

# Build
RUN source /opt/ros/$ROS_DISTRO/setup.bash && \
colcon build --parallel-workers $(nproc) --symlink-install \
Expand Down Expand Up @@ -112,12 +137,12 @@ RUN echo "Europe/Paris" > /etc/localtime ; echo "CUDA Version ${CUDA_MAJOR}.${CU
ln -sf /lib/x86_64-linux-gnu/libusb-1.0.so.0 /usr/lib/x86_64-linux-gnu/libusb-1.0.so && \
rm ZED_SDK_Linux_Ubuntu.run && \
rm -rf /var/lib/apt/lists/*

# ROS install
ENV ROS_DISTRO $ROS_DISTRO
RUN echo "deb http://packages.ros.org/ros2/ubuntu jammy main" > /etc/apt/sources.list.d/ros2-latest.list && \
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 && \
apt-get update && \
apt-get update && \
apt-get install -y --no-install-recommends \
ros-$ROS_DISTRO-ros-core \
&& rm -rf /var/lib/apt/lists/*
Expand Down Expand Up @@ -162,7 +187,17 @@ RUN apt-get update && apt-get install -y \
# Git action version
RUN echo $(cat /ros2_ws/src/zed-ros2-wrapper/zed_wrapper/package.xml | grep '<version>' | sed -r 's/.*<version>([0-9]+.[0-9]+.[0-9]+)<\/version>/\1/g') >> /version.txt

COPY ./ros_entrypoint.sh /

COPY ./healthcheck.sh /
HEALTHCHECK --interval=7s --timeout=2s --start-period=5s --retries=5 \
CMD ["/healthcheck.sh"]

# Add Husarnet
COPY --from=husarnet-dds-getter /usr/bin/husarnet-dds /usr/bin/husarnet-dds
RUN chmod +x /usr/bin/husarnet-dds

# Setup environment variables
COPY ./ros_entrypoint.sh /ros_entrypoint.sh
ENTRYPOINT ["/ros_entrypoint.sh"]
CMD ["bash"]
CMD ["bash"]
24 changes: 22 additions & 2 deletions Dockerfile.jetson
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ RUN apt-get update && \
rosdep install --from-paths src -y -i && \
rm -rf /var/lib/apt/lists/*

# Create health check package
RUN cd src/ && \
source /opt/ros/$ROS_DISTRO/setup.bash && \
ros2 pkg create healthcheck_pkg --build-type ament_cmake --dependencies rclcpp sensor_msgs && \
sed -i '/find_package(sensor_msgs REQUIRED)/a \
add_executable(healthcheck_node src/healthcheck.cpp)\n \
ament_target_dependencies(healthcheck_node rclcpp sensor_msgs)\n \
install(TARGETS healthcheck_node DESTINATION lib/${PROJECT_NAME})' \
/ros2_ws/src/healthcheck_pkg/CMakeLists.txt

COPY ./healthcheck.cpp /ros2_ws/src/healthcheck_pkg/src/

# Build
WORKDIR /ros2_ws
RUN source /opt/ros/$ROS_DISTRO/setup.bash && \
Expand Down Expand Up @@ -192,9 +204,17 @@ RUN test -f "/ros2_ws/install/setup.bash" && echo "source /ros2_ws/install/setup
# Git action version
RUN echo $(cat /ros2_ws/src/zed-ros2-wrapper/zed_wrapper/package.xml | grep '<version>' | sed -r 's/.*<version>([0-9]+.[0-9]+.[0-9]+)<\/version>/\1/g') >> /version.txt

# Setup environment variables
COPY ./ros_entrypoint.sh /

COPY ./healthcheck.sh /
HEALTHCHECK --interval=7s --timeout=2s --start-period=5s --retries=5 \
CMD ["/healthcheck.sh"]

# Add Husarnet
COPY --from=husarnet-dds-getter /usr/bin/husarnet-dds /usr/bin/husarnet-dds
RUN chmod +x /usr/bin/husarnet-dds

# Setup environment variables
COPY ./ros_entrypoint.sh /ros_entrypoint.sh
ENTRYPOINT ["/ros_entrypoint.sh"]
CMD ["bash"]
CMD ["bash"]
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ The repository contains a GitHub Actions workflow for auto-deployment of built D
## Available Docker Images

**ROS1:**

- **`husarion/zed-desktop:noetic`** for desktop platform with CUDA (tested on platform with 11.7).
- **`husarion/zed-desktop-cpu:noetic`** a simple demo version on the CPU, allowing you to check if the camera and IMU are working properly. Image dedicated to platforms with amd64 and arm64 architecture.
- **`husarion/zed-jetson:noetic`** for Jetson platform currently support - **Jetson Xavier, Orin AGX/NX/Nano, CUDA 11.4** (tested on Xavier AGX).
- **`husarion/zed-jetson:melodic`** for Jetson platform currently not supported - **Jetson Nano, TX2/TX2 NX, CUDA 10.2** (tested on Nano).

**ROS2:**

- **`husarion/zed-desktop:humble`** for desktop platform with CUDA (tested on platform with 11.7).
- **`husarion/zed-desktop-cpu:humble`** a simple demo version on the CPU, allowing you to check if the camera and IMU are working properly. Image dedicated to platforms with amd64 and arm64 architecture.
- **`husarion/zed-jetson:foxy`** for Jetson platform currently support - **Jetson Xavier, Orin AGX/NX/Nano, CUDA 11.4** (tested on Xavier AGX).
Expand Down Expand Up @@ -42,15 +44,17 @@ cd zed-docker/demo
```bash
export ZED_IMAGE=<zed_image>
```
Replace `<zed_image>` with appropriate Docker imagefrom below table.

<div class="center-table">
Replace `<zed_image>` with appropriate Docker image from below table.

<div style="display: flex; justify-content: center;">

| **Docker Image** |
| ---------------------------------- |
| husarion/zed-jetson:foxy |
| husarion/zed-desktop:humble |
| husarion/zed-desktop-cpu:humble |

</div>

**3. Select the appropriate launch file**

Expand All @@ -60,7 +64,7 @@ export CAMERA_LAUNCH=<camera_launch>

Replace `<camera_launch>` with appropriate launch file for your camera from below table.

<div class="center-table">
<div style="display: flex; justify-content: center;">

| **Product name** | **Launch file** |
| ----------------- | ----------------------- |
Expand All @@ -71,6 +75,8 @@ Replace `<camera_launch>` with appropriate launch file for your camera from belo
| ZED X | zedx.launch.py |
| ZED X Mini | zedxm.launch.py |

</div>

**4. Activate the Device**

```bash
Expand All @@ -93,6 +99,7 @@ docker compose up rviz
**6. Configure RViz.**

Add following topic to RViz:

- RGB image topic: `/<camera_model>/zed_node/rgb/image_rect_color`
- Point cloud topic: `/<camera_model>/zed_node/point_cloud/cloud_registered`

Expand Down
4 changes: 3 additions & 1 deletion demo/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ services:
network_mode: host
ipc: host
runtime: nvidia
environment:
- CAMERA_LAUNCH=${CAMERA_LAUNCH:-err}
volumes:
- ./params:/ros2_ws/src/zed-ros-wrapper/zed_wrapper/params
- /dev/shm:/dev/shm
Expand All @@ -26,4 +28,4 @@ services:
- DISPLAY
- LIBGL_ALWAYS_SOFTWARE=1
- ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-0}
- RMW_IMPLEMENTATION=${RMW_IMPLEMENTATION:-rmw_fastrtps_cpp}
- RMW_IMPLEMENTATION=${RMW_IMPLEMENTATION:-rmw_fastrtps_cpp}
59 changes: 59 additions & 0 deletions healthcheck.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "fstream"
#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/image.hpp"

using namespace std::chrono_literals;

#define LOOP_PERIOD 2s
#define MSG_VALID_TIME 5s

std::chrono::steady_clock::time_point last_msg_time;

void write_health_status(const std::string &status) {
std::ofstream healthFile("/health_status.txt");
healthFile << status;
}

void msg_callback(const sensor_msgs::msg::Image::SharedPtr msg) {
last_msg_time = std::chrono::steady_clock::now();
}

void healthy_check() {
std::chrono::steady_clock::time_point current_time =
std::chrono::steady_clock::now();
std::chrono::duration<double> elapsed_time = current_time - last_msg_time;
bool is_msg_valid = elapsed_time.count() < MSG_VALID_TIME.count();

if (is_msg_valid) {
write_health_status("healthy");
} else {
write_health_status("unhealthy");
}
}

int main(int argc, char *argv[]) {
rclcpp::init(argc, argv);
auto node = rclcpp::Node::make_shared("healthcheck_node");
char *zed = std::getenv("CAMERA_LAUNCH");

if (zed) {
std::string zed_str(zed);
zed_str = zed_str.substr(0, zed_str.find('.'));
std::string topic_name = zed_str + "/zed_node/rgb/image_rect_color";

std::cout << topic_name << std::endl;
auto sub = node->create_subscription<sensor_msgs::msg::Image>(
topic_name, rclcpp::SensorDataQoS(), msg_callback);

while (rclcpp::ok()) {
rclcpp::spin_some(node);
healthy_check();
std::this_thread::sleep_for(LOOP_PERIOD);
}
} else {
std::cerr << "CAMERA_LAUNCH environment variable not set" << std::endl;
return 1;
}

return 0;
}
17 changes: 17 additions & 0 deletions healthcheck.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

HEALTHCHECK_FILE="/health_status.txt"


# Now check the health status
if [ -f "$HEALTHCHECK_FILE" ]; then
status=$(cat "$HEALTHCHECK_FILE")
if [ "$status" == "healthy" ]; then
exit 0
else
exit 1
fi
else
echo "Healthcheck file still not found. There may be an issue with the node."
exit 1
fi
15 changes: 9 additions & 6 deletions ros_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
#!/bin/bash
set -e

output=$(husarnet-dds singleshot) || true
if [[ "$HUSARNET_DDS_DEBUG" == "TRUE" ]]; then
echo "$output"
fi
# Run husarnet-dds singleshot and capture the output
output=$(husarnet-dds singleshot || true)
[[ "$HUSARNET_DDS_DEBUG" == "TRUE" ]] && echo "$output"

# setup ROS2 environment
# Setup ROS environment
source "/opt/ros/$ROS_DISTRO/setup.bash"
test -f "/ros2_ws/install/setup.bash" && source "/ros2_ws/install/setup.bash"

exec "$@"
# Run healthcheck in the background
ros2 run healthcheck_pkg healthcheck_node &

# Execute additional commands
exec "$@"

0 comments on commit 8aa41f3

Please sign in to comment.