From 3a82c09b2dc1ed811ae07cbb6433e092a0652e8b Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Wed, 21 Feb 2024 03:08:48 +0000 Subject: [PATCH 01/15] Add traffic light launch file --- modules/docker-compose.perception.yaml | 1 + .../config/traffic_light_config.yaml | 7 +++++ .../launch/traffic_light_launch.py | 26 +++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100755 src/perception/camera_object_detection/config/traffic_light_config.yaml create mode 100755 src/perception/camera_object_detection/launch/traffic_light_launch.py diff --git a/modules/docker-compose.perception.yaml b/modules/docker-compose.perception.yaml index 3614af7d..e714137f 100644 --- a/modules/docker-compose.perception.yaml +++ b/modules/docker-compose.perception.yaml @@ -31,6 +31,7 @@ services: command: /bin/bash -c "ros2 launch camera_object_detection eve_launch.py" volumes: - /mnt/wato-drive2/perception_models/yolov8s.pt:/perception_models/yolov8s.pt + - /mnt/wato-drive2/perception_models/traffic_light.pt:/perception_models/traffic_light.pt lidar_object_detection: build: diff --git a/src/perception/camera_object_detection/config/traffic_light_config.yaml b/src/perception/camera_object_detection/config/traffic_light_config.yaml new file mode 100755 index 00000000..39481c1c --- /dev/null +++ b/src/perception/camera_object_detection/config/traffic_light_config.yaml @@ -0,0 +1,7 @@ +camera_object_detection_node: + ros__parameters: + camera_topic: /camera/left/image_color + publish_vis_topic: /camera/left/annotated_traffic_lights + publish_detection_topic: /traffic_lights + model_path: /perception_models/traffic_light.pt + image_size: 480 diff --git a/src/perception/camera_object_detection/launch/traffic_light_launch.py b/src/perception/camera_object_detection/launch/traffic_light_launch.py new file mode 100755 index 00000000..346b560a --- /dev/null +++ b/src/perception/camera_object_detection/launch/traffic_light_launch.py @@ -0,0 +1,26 @@ +from launch import LaunchDescription +from launch_ros.actions import Node +from ament_index_python.packages import get_package_share_directory +import os + + +def generate_launch_description(): + ld = LaunchDescription() + config = os.path.join( + get_package_share_directory('camera_object_detection'), + 'config', + 'traffic_light_config.yaml' + ) + + # nodes + camera_object_detection_node = Node( + package='camera_object_detection', + executable='camera_object_detection_node', + name='camera_object_detection_node', + parameters=[config] + ) + + # finalize + ld.add_action(camera_object_detection_node) + + return ld From 7477c954bff2662cae13ba37e37071c292405727 Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Wed, 21 Feb 2024 06:20:13 +0000 Subject: [PATCH 02/15] Add traffic light --- modules/docker-compose.perception.yaml | 2 +- .../yolov8_detection.py | 36 +++++++++++++------ .../config/traffic_light_config.yaml | 9 ++--- .../launch/traffic_light_launch.py | 2 +- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/modules/docker-compose.perception.yaml b/modules/docker-compose.perception.yaml index e714137f..90e7b7cd 100644 --- a/modules/docker-compose.perception.yaml +++ b/modules/docker-compose.perception.yaml @@ -31,7 +31,7 @@ services: command: /bin/bash -c "ros2 launch camera_object_detection eve_launch.py" volumes: - /mnt/wato-drive2/perception_models/yolov8s.pt:/perception_models/yolov8s.pt - - /mnt/wato-drive2/perception_models/traffic_light.pt:/perception_models/traffic_light.pt + - /mnt/wato-drive2/perception_models/traffic_light_v5.pt:/perception_models/traffic_light_v5.pt lidar_object_detection: build: diff --git a/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py b/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py index b5ad2ea8..3bf3f47d 100755 --- a/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py +++ b/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py @@ -9,7 +9,7 @@ ) from ultralytics.nn.autobackend import AutoBackend -from ultralytics.data.augment import LetterBox +from ultralytics.data.augment import LetterBox, CenterCrop from ultralytics.utils.ops import non_max_suppression from ultralytics.utils.plotting import Annotator, colors @@ -35,8 +35,11 @@ def __init__(self): self.declare_parameter("publish_vis_topic", "/annotated_img") self.declare_parameter("publish_detection_topic", "/detections") self.declare_parameter("model_path", "/perception_models/yolov8s.pt") - self.declare_parameter("image_size", 480) + self.declare_parameter("image_size", 1024) self.declare_parameter("compressed", False) + self.declare_parameter("crop_mode", "LetterBox") + + self.counter = 0 self.camera_topic = self.get_parameter("camera_topic").value self.publish_vis_topic = self.get_parameter("publish_vis_topic").value @@ -45,10 +48,10 @@ def __init__(self): self.model_path = self.get_parameter("model_path").value self.image_size = self.get_parameter("image_size").value self.compressed = self.get_parameter("compressed").value + self.crop_mode = self.get_parameter("crop_mode").value self.line_thickness = 1 self.half = False - self.augment = False self.subscription = self.create_subscription( Image if not self.compressed else CompressedImage, @@ -90,7 +93,19 @@ def __init__(self): self.get_logger().info( f"Successfully created node listening on camera topic: {self.camera_topic}...") - def preprocess_image(self, cv_image): + def crop_image(self, cv_image): + if self.crop_mode == "LetterBox": + img = LetterBox(self.image_size, stride=self.stride)( + image=cv_image) + elif self.crop_mode == "CenterCrop": + img = CenterCrop(self.image_size)(cv_image) + else: + raise Exception( + "Invalid crop mode, please choose either 'LetterBox' or 'CenterCrop'!") + + return img + + def preprocess_and_convert_to_tensor(self, cv_image): """ Preprocess the image by resizing, padding and rearranging the dimensions. @@ -100,9 +115,7 @@ def preprocess_image(self, cv_image): Returns: torch.Tensor image for model input of shape (1,3,w,h) """ - # Padded resize - img = cv_image - img = LetterBox(self.image_size, stride=self.stride)(image=cv_image) + img = self.crop_image(cv_image) # Convert img = img.transpose(2, 0, 1) @@ -196,9 +209,8 @@ def image_callback(self, msg): return # preprocess image and run through prediction - img = self.preprocess_image(cv_image) - processed_cv_image = LetterBox( - self.image_size, stride=self.stride)(image=cv_image) + img = self.preprocess_and_convert_to_tensor(cv_image) + processed_cv_image = self.crop_image(cv_image) pred = self.model(img) # nms function used same as yolov8 detect.py @@ -240,6 +252,10 @@ def image_callback(self, msg): self.publish_vis(annotated_img, feed) self.publish_detections(detections, msg, feed) + cv2.imwrite( + f"traffic_light_4/src_img{self.counter}.jpg", annotated_img) + self.counter += 1 + self.get_logger().info( f"Finished in: {time.time() - startTime}, {1/(time.time() - startTime)} Hz") diff --git a/src/perception/camera_object_detection/config/traffic_light_config.yaml b/src/perception/camera_object_detection/config/traffic_light_config.yaml index 39481c1c..c93c8e91 100755 --- a/src/perception/camera_object_detection/config/traffic_light_config.yaml +++ b/src/perception/camera_object_detection/config/traffic_light_config.yaml @@ -1,7 +1,8 @@ -camera_object_detection_node: +traffic_light_node: ros__parameters: camera_topic: /camera/left/image_color - publish_vis_topic: /camera/left/annotated_traffic_lights + publish_vis_topic: /annotated_traffic_lights publish_detection_topic: /traffic_lights - model_path: /perception_models/traffic_light.pt - image_size: 480 + model_path: /perception_models/traffic_light_v5.pt + crop_mode: CenterCrop + image_size: 1024 diff --git a/src/perception/camera_object_detection/launch/traffic_light_launch.py b/src/perception/camera_object_detection/launch/traffic_light_launch.py index 346b560a..f59035de 100755 --- a/src/perception/camera_object_detection/launch/traffic_light_launch.py +++ b/src/perception/camera_object_detection/launch/traffic_light_launch.py @@ -16,7 +16,7 @@ def generate_launch_description(): camera_object_detection_node = Node( package='camera_object_detection', executable='camera_object_detection_node', - name='camera_object_detection_node', + name='traffic_light_node', parameters=[config] ) From 73eb957bd90583c5f52d4eada714eece05e6af74 Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Wed, 21 Feb 2024 06:25:57 +0000 Subject: [PATCH 03/15] Remove counter --- .../camera_object_detection/yolov8_detection.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py b/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py index 3bf3f47d..65285466 100755 --- a/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py +++ b/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py @@ -39,8 +39,6 @@ def __init__(self): self.declare_parameter("compressed", False) self.declare_parameter("crop_mode", "LetterBox") - self.counter = 0 - self.camera_topic = self.get_parameter("camera_topic").value self.publish_vis_topic = self.get_parameter("publish_vis_topic").value self.publish_detection_topic = self.get_parameter( @@ -156,10 +154,11 @@ def postprocess_detections(self, detections, annotator): annotator_img = annotator.result() return (processed_detections, annotator_img) - def publish_vis(self, annotated_img, feed): + def publish_vis(self, annotated_img, msg, feed): # Publish visualizations imgmsg = self.cv_bridge.cv2_to_imgmsg(annotated_img, "bgr8") - imgmsg.header.frame_id = "camera_{}_link".format(feed) + imgmsg.header.stamp = msg.header.stamp + imgmsg.header.frame_id = msg.header.frame_id self.vis_publisher.publish(imgmsg) def publish_detections(self, detections, msg, feed): @@ -249,13 +248,8 @@ def image_callback(self, msg): # Currently we support a single camera so we pass an empty string feed = "" - self.publish_vis(annotated_img, feed) + self.publish_vis(annotated_img, msg, feed) self.publish_detections(detections, msg, feed) - - cv2.imwrite( - f"traffic_light_4/src_img{self.counter}.jpg", annotated_img) - self.counter += 1 - self.get_logger().info( f"Finished in: {time.time() - startTime}, {1/(time.time() - startTime)} Hz") From c7a1fc3b2c54bbd7afcf8a20f8bf0938e50ecccb Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Fri, 23 Feb 2024 05:12:54 +0000 Subject: [PATCH 04/15] Remove traffic light detection dockerfile --- .../traffic_light_detection.Dockerfile | 55 ------------------- .../docker-compose.perception.yaml | 9 --- modules/docker-compose.perception.yaml | 10 ---- 3 files changed, 74 deletions(-) delete mode 100644 docker/perception/traffic_light_detection/traffic_light_detection.Dockerfile diff --git a/docker/perception/traffic_light_detection/traffic_light_detection.Dockerfile b/docker/perception/traffic_light_detection/traffic_light_detection.Dockerfile deleted file mode 100644 index d91b79e5..00000000 --- a/docker/perception/traffic_light_detection/traffic_light_detection.Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -ARG BASE_IMAGE=ghcr.io/watonomous/wato_monorepo/base:humble-ubuntu22.04 - -################################ Source ################################ -FROM ${BASE_IMAGE} as source - -WORKDIR ${AMENT_WS}/src - -# Copy in source code -COPY src/perception/traffic_light_detection traffic_light_detection -COPY src/wato_msgs/sample_msgs sample_msgs - -# Scan for rosdeps -RUN apt-get -qq update && rosdep update && \ - rosdep install --from-paths . --ignore-src -r -s \ - | grep 'apt-get install' \ - | awk '{print $3}' \ - | sort > /tmp/colcon_install_list - -################################# Dependencies ################################ -FROM ${BASE_IMAGE} as dependencies - -# Install Rosdep requirements -COPY --from=source /tmp/colcon_install_list /tmp/colcon_install_list -RUN apt-fast install -qq -y --no-install-recommends $(cat /tmp/colcon_install_list) - -# Copy in source code from source stage -WORKDIR ${AMENT_WS} -COPY --from=source ${AMENT_WS}/src src - -# Dependency Cleanup -WORKDIR / -RUN apt-get -qq autoremove -y && apt-get -qq autoclean && apt-get -qq clean && \ - rm -rf /root/* /root/.ros /tmp/* /var/lib/apt/lists/* /usr/share/doc/* - -################################ Build ################################ -FROM dependencies as build - -# Build ROS2 packages -WORKDIR ${AMENT_WS} -RUN . /opt/ros/$ROS_DISTRO/setup.sh && \ - colcon build \ - --cmake-args -DCMAKE_BUILD_TYPE=Release - -# Entrypoint will run before any CMD on launch. Sources ~/opt//setup.bash and ~/ament_ws/install/setup.bash -COPY docker/wato_ros_entrypoint.sh ${AMENT_WS}/wato_ros_entrypoint.sh -ENTRYPOINT ["./wato_ros_entrypoint.sh"] - -################################ Prod ################################ -FROM build as deploy - -# Source Cleanup and Security Setup -RUN chown -R $USER:$USER ${AMENT_WS} -RUN rm -rf src/* - -USER ${USER} diff --git a/modules/dev_overrides/docker-compose.perception.yaml b/modules/dev_overrides/docker-compose.perception.yaml index 31b41896..07e28ec2 100644 --- a/modules/dev_overrides/docker-compose.perception.yaml +++ b/modules/dev_overrides/docker-compose.perception.yaml @@ -32,15 +32,6 @@ services: volumes: - ${MONO_DIR}/src/perception/lidar_object_detection:/home/bolty/ament_ws/src/lidar_object_detection - traffic_light_detection: - <<: *fixuid - extends: - file: ../docker-compose.perception.yaml - service: traffic_light_detection - command: tail -F anything - volumes: - - ${MONO_DIR}/src/perception/traffic_light_detection:/home/bolty/ament_ws/src/traffic_light_detection - traffic_sign_detection: <<: *fixuid extends: diff --git a/modules/docker-compose.perception.yaml b/modules/docker-compose.perception.yaml index 90e7b7cd..55c06851 100644 --- a/modules/docker-compose.perception.yaml +++ b/modules/docker-compose.perception.yaml @@ -43,16 +43,6 @@ services: target: deploy image: "${PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE}:${TAG}" command: /bin/bash -c "ros2 launch lidar_object_detection lidar_object_detection.launch.py" - traffic_light_detection: - build: - context: .. - dockerfile: docker/perception/traffic_light_detection/traffic_light_detection.Dockerfile - cache_from: - - "${PERCEPTION_TRAFFIC_LIGHT_DETECTION_IMAGE}:${TAG}" - - "${PERCEPTION_TRAFFIC_LIGHT_DETECTION_IMAGE}:main" - target: deploy - image: "${PERCEPTION_TRAFFIC_LIGHT_DETECTION_IMAGE}:${TAG}" - command: /bin/bash -c "ros2 launch traffic_light_detection traffic_light_detection.launch.py" traffic_sign_detection: build: From e179ec95a2996986cdf05fe5717fddb0f7a8a3fb Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Fri, 23 Feb 2024 17:34:16 +0000 Subject: [PATCH 05/15] Add centercrop and letterbox crop --- modules/docker-compose.perception.yaml | 2 +- .../yolov8_detection.py | 60 +++++++++++++++++-- .../config/traffic_light_config.yaml | 3 +- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/modules/docker-compose.perception.yaml b/modules/docker-compose.perception.yaml index 55c06851..bba13303 100644 --- a/modules/docker-compose.perception.yaml +++ b/modules/docker-compose.perception.yaml @@ -31,7 +31,7 @@ services: command: /bin/bash -c "ros2 launch camera_object_detection eve_launch.py" volumes: - /mnt/wato-drive2/perception_models/yolov8s.pt:/perception_models/yolov8s.pt - - /mnt/wato-drive2/perception_models/traffic_light_v5.pt:/perception_models/traffic_light_v5.pt + - /mnt/wato-drive2/perception_models/traffic_light.pt:/perception_models/traffic_light.pt lidar_object_detection: build: diff --git a/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py b/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py index 65285466..966a4a2b 100755 --- a/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py +++ b/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py @@ -1,5 +1,6 @@ import rclpy from rclpy.node import Node +import os from sensor_msgs.msg import Image, CompressedImage from vision_msgs.msg import ( @@ -38,6 +39,7 @@ def __init__(self): self.declare_parameter("image_size", 1024) self.declare_parameter("compressed", False) self.declare_parameter("crop_mode", "LetterBox") + self.declare_parameter("save_detections", False) self.camera_topic = self.get_parameter("camera_topic").value self.publish_vis_topic = self.get_parameter("publish_vis_topic").value @@ -47,6 +49,11 @@ def __init__(self): self.image_size = self.get_parameter("image_size").value self.compressed = self.get_parameter("compressed").value self.crop_mode = self.get_parameter("crop_mode").value + self.save_detections = bool(self.get_parameter("save_detections").value) + self.counter = 0 # For saving detections + if self.save_detections: + if not os.path.exists("detections"): + os.makedirs("detections") self.line_thickness = 1 self.half = False @@ -61,6 +68,9 @@ def __init__(self): depth=10, ), ) + + self.orig_image_width = None + self.orig_image_height = None # set device self.device = torch.device( @@ -103,7 +113,39 @@ def crop_image(self, cv_image): return img - def preprocess_and_convert_to_tensor(self, cv_image): + def convert_bboxes_to_orig_frame(self, bbox): + """ + Converts bounding box coordinates from the scaled image frame back to the original image frame. + + This function takes into account the original image dimensions and the scaling method used + (either "LetterBox" or "CenterCrop") to accurately map the bounding box coordinates back to + their original positions in the original image. + + Parameters: + bbox (list): A list containing the bounding box coordinates in the format [x1, y1, w1, h1] + in the scaled image frame. + + Returns: + list: A list containing the bounding box coordinates in the format [x1, y1, w1, h1] + in the original image frame. + + """ + width_scale = self.orig_image_width / self.image_size + height_scale = self.orig_image_height / self.image_size + if self.crop_mode == "LetterBox": + translation = (self.image_size - self.orig_image_height / width_scale) / 2 + return [bbox[0] * width_scale, + (bbox[1] - translation) * width_scale, + bbox[2] * width_scale, + bbox[3] * width_scale] + elif self.crop_mode == "CenterCrop": + translation = (self.orig_image_width / height_scale - self.image_size) / 2 + return [(bbox[0] + translation) * height_scale, + bbox[1] * height_scale, + bbox[2] * height_scale, + bbox[3] * height_scale] + + def crop_and_convert_to_tensor(self, cv_image): """ Preprocess the image by resizing, padding and rearranging the dimensions. @@ -187,10 +229,13 @@ def publish_detections(self, detections, msg, feed): detection2darray.detections.append(detection2d) self.detection_publisher.publish(detection2darray) - return def image_callback(self, msg): self.get_logger().debug("Received image") + if (self.orig_image_width is None): + self.orig_image_width = msg.width + self.orig_image_height = msg.height + images = [msg] # msg is a single sensor image startTime = time.time() for image in images: @@ -208,8 +253,7 @@ def image_callback(self, msg): return # preprocess image and run through prediction - img = self.preprocess_and_convert_to_tensor(cv_image) - processed_cv_image = self.crop_image(cv_image) + img = self.crop_and_convert_to_tensor(cv_image) pred = self.model(img) # nms function used same as yolov8 detect.py @@ -228,6 +272,7 @@ def image_callback(self, msg): xyxy[3] - xyxy[1], ] bbox = [b.item() for b in bbox] + bbox = self.convert_bboxes_to_orig_frame(bbox) detections.append( { @@ -239,7 +284,7 @@ def image_callback(self, msg): self.get_logger().debug(f"{label}: {bbox}") annotator = Annotator( - processed_cv_image, + cv_image, line_width=self.line_thickness, example=str(self.names), ) @@ -250,6 +295,11 @@ def image_callback(self, msg): feed = "" self.publish_vis(annotated_img, msg, feed) self.publish_detections(detections, msg, feed) + + if self.save_detections: + cv2.imwrite(f"detections/{self.counter}.jpg", annotated_img) + self.counter += 1 + self.get_logger().info( f"Finished in: {time.time() - startTime}, {1/(time.time() - startTime)} Hz") diff --git a/src/perception/camera_object_detection/config/traffic_light_config.yaml b/src/perception/camera_object_detection/config/traffic_light_config.yaml index c93c8e91..e74e41a9 100755 --- a/src/perception/camera_object_detection/config/traffic_light_config.yaml +++ b/src/perception/camera_object_detection/config/traffic_light_config.yaml @@ -3,6 +3,7 @@ traffic_light_node: camera_topic: /camera/left/image_color publish_vis_topic: /annotated_traffic_lights publish_detection_topic: /traffic_lights - model_path: /perception_models/traffic_light_v5.pt + model_path: /perception_models/traffic_light.pt crop_mode: CenterCrop image_size: 1024 + save_detections: false From a33624038d12069e90e0251c4c09aaae199099f3 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 23 Feb 2024 13:28:33 -0500 Subject: [PATCH 06/15] Update topic names --- .../camera_object_detection/config/eve_config.yaml | 12 ++++++------ .../config/traffic_light_config.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/perception/camera_object_detection/config/eve_config.yaml b/src/perception/camera_object_detection/config/eve_config.yaml index 11687c55..89cc3774 100755 --- a/src/perception/camera_object_detection/config/eve_config.yaml +++ b/src/perception/camera_object_detection/config/eve_config.yaml @@ -1,23 +1,23 @@ left_camera_object_detection_node: ros__parameters: camera_topic: /camera/left/image_color - publish_vis_topic: /camera/left/annotated_img - publish_detection_topic: /camera/left/detections + publish_vis_topic: /camera/left/camera_detections_viz + publish_detection_topic: /camera/left/camera_detections model_path: /perception_models/yolov8s.pt image_size: 480 center_camera_object_detection_node: ros__parameters: camera_topic: /camera/center/image_color - publish_vis_topic: /camera/center/annotated_img - publish_detection_topic: /camera/center/detections + publish_vis_topic: /camera/center/camera_detections_viz + publish_detection_topic: /camera/center/camera_detections model_path: /perception_models/yolov8s.pt image_size: 480 right_camera_object_detection_node: ros__parameters: camera_topic: /camera/right/image_color - publish_vis_topic: /camera/right/annotated_img - publish_detection_topic: /camera/right/detections + publish_vis_topic: /camera/right/camera_detections_viz + publish_detection_topic: /camera/right/camera_detections model_path: /perception_models/yolov8s.pt image_size: 480 diff --git a/src/perception/camera_object_detection/config/traffic_light_config.yaml b/src/perception/camera_object_detection/config/traffic_light_config.yaml index e74e41a9..9a3e00c8 100755 --- a/src/perception/camera_object_detection/config/traffic_light_config.yaml +++ b/src/perception/camera_object_detection/config/traffic_light_config.yaml @@ -1,7 +1,7 @@ traffic_light_node: ros__parameters: camera_topic: /camera/left/image_color - publish_vis_topic: /annotated_traffic_lights + publish_vis_topic: /traffic_lights_viz publish_detection_topic: /traffic_lights model_path: /perception_models/traffic_light.pt crop_mode: CenterCrop From 7b44a623e3528e28434fd0afe0f79f78f5b7e6dd Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Fri, 8 Mar 2024 01:34:38 +0000 Subject: [PATCH 07/15] Remove traffic light remnant --- watod_scripts/watod-setup-env.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/watod_scripts/watod-setup-env.sh b/watod_scripts/watod-setup-env.sh index 383b763c..dc8d683b 100755 --- a/watod_scripts/watod-setup-env.sh +++ b/watod_scripts/watod-setup-env.sh @@ -87,7 +87,6 @@ INFRASTRUCTURE_FOXGLOVE_IMAGE=${DATA_STREAM_IMAGE:-"$REGISTRY_URL/infrastructure PERCEPTION_RADAR_OBJECT_DETECTION_IMAGE=${PERCEPTION_RADAR_OBJECT_DETECTION_IMAGE:-"$REGISTRY_URL/perception/radar_object_detection"} PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE=${PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE:-"$REGISTRY_URL/perception/lidar_object_detection"} PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE=${PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE:-"$REGISTRY_URL/perception/camera_object_detection"} -PERCEPTION_TRAFFIC_LIGHT_DETECTION_IMAGE=${PERCEPTION_TRAFFIC_LIGHT_DETECTION_IMAGE:-"$REGISTRY_URL/perception/traffic_light_detection"} PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE=${PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE:-"$REGISTRY_URL/perception/traffic_sign_detection"} PERCEPTION_LANE_DETECTION_IMAGE=${PERCEPTION_LANE_DETECTION_IMAGE:-"$REGISTRY_URL/perception/lane_detection"} PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE=${PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE:-"$REGISTRY_URL/perception/semantic_segmentation"} @@ -173,7 +172,6 @@ echo "INFRASTRUCTURE_FOXGLOVE_IMAGE=$INFRASTRUCTURE_FOXGLOVE_IMAGE" >> "$MODULES echo "PERCEPTION_RADAR_OBJECT_DETECTION_IMAGE=$PERCEPTION_RADAR_OBJECT_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE=$PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE=$PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE" >> "$MODULES_DIR/.env" -echo "PERCEPTION_TRAFFIC_LIGHT_DETECTION_IMAGE=$PERCEPTION_TRAFFIC_LIGHT_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE=$PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_LANE_DETECTION_IMAGE=$PERCEPTION_LANE_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE=$PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE" >> "$MODULES_DIR/.env" From aa068790b4503f7459b9355b51868a9f6fb2fc12 Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Fri, 8 Mar 2024 01:58:02 +0000 Subject: [PATCH 08/15] Clean up launch files --- ...eepracer_launch.py => deepracer.launch.py} | 7 +-- .../launch/eve.launch.py | 49 +++++++++++++++++++ .../pretrained_yolov8.launch.py} | 15 +++--- .../traffic_light.launch.py} | 7 +-- ...{nuscenes_launch.py => nuscenes.launch.py} | 5 +- 5 files changed, 58 insertions(+), 25 deletions(-) rename src/perception/camera_object_detection/launch/{deepracer_launch.py => deepracer.launch.py} (82%) create mode 100755 src/perception/camera_object_detection/launch/eve.launch.py rename src/perception/camera_object_detection/launch/{eve_launch.py => include/pretrained_yolov8.launch.py} (81%) mode change 100755 => 100644 rename src/perception/camera_object_detection/launch/{traffic_light_launch.py => include/traffic_light.launch.py} (82%) rename src/perception/camera_object_detection/launch/{nuscenes_launch.py => nuscenes.launch.py} (87%) diff --git a/src/perception/camera_object_detection/launch/deepracer_launch.py b/src/perception/camera_object_detection/launch/deepracer.launch.py similarity index 82% rename from src/perception/camera_object_detection/launch/deepracer_launch.py rename to src/perception/camera_object_detection/launch/deepracer.launch.py index c853a556..138c32b4 100755 --- a/src/perception/camera_object_detection/launch/deepracer_launch.py +++ b/src/perception/camera_object_detection/launch/deepracer.launch.py @@ -5,14 +5,12 @@ def generate_launch_description(): - ld = LaunchDescription() config = os.path.join( get_package_share_directory('camera_object_detection'), 'config', 'deeepracer.yaml' ) - # nodes camera_object_detection_node = Node( package='camera_object_detection', executable='camera_object_detection_node', @@ -20,7 +18,4 @@ def generate_launch_description(): parameters=[config] ) - # finalize - ld.add_action(camera_object_detection_node) - - return ld + return LaunchDescription([camera_object_detection_node]) diff --git a/src/perception/camera_object_detection/launch/eve.launch.py b/src/perception/camera_object_detection/launch/eve.launch.py new file mode 100755 index 00000000..a39c0ef2 --- /dev/null +++ b/src/perception/camera_object_detection/launch/eve.launch.py @@ -0,0 +1,49 @@ +from launch import LaunchDescription +from launch.substitutions import LaunchConfiguration +from launch.conditions import LaunchConfigurationEquals +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from ament_index_python.packages import get_package_share_directory +import os + + +def generate_launch_description(): + launch_traffic_light = LaunchConfiguration('launch_traffic_light', default=True) + launch_traffic_light_arg = DeclareLaunchArgument('launch_traffic_light', + default_value=launch_traffic_light, + description='Launch traffic light detection') + launch_traffic_sign = LaunchConfiguration('launch_traffic_sign', default=True) + launch_traffic_sign_arg = DeclareLaunchArgument('launch_traffic_sign', + default_value=launch_traffic_sign, + description='Launch traffic sign detection') + + launch_args = [launch_traffic_light_arg, + launch_traffic_sign_arg] + + camera_object_detection_launch_include_dir = os.path.join( + get_package_share_directory('carter_navigation'), 'launch', 'include') + + pretrained_yolov8_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [camera_object_detection_launch_include_dir, '/pretrained_yolov8.launch.py']), + ) + + traffic_light_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [camera_object_detection_launch_include_dir, '/traffic_light.launch.py']), + condition=LaunchConfigurationEquals( + 'launch_traffic_light', 'True') + ) + + traffic_sign_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [camera_object_detection_launch_include_dir, '/traffic_sign.launch.py']), + condition=LaunchConfigurationEquals( + 'launch_traffic_sign', 'True') + ) + + return LaunchDescription(launch_args + [ + pretrained_yolov8_launch, + traffic_light_launch, + traffic_sign_launch + ]) diff --git a/src/perception/camera_object_detection/launch/eve_launch.py b/src/perception/camera_object_detection/launch/include/pretrained_yolov8.launch.py old mode 100755 new mode 100644 similarity index 81% rename from src/perception/camera_object_detection/launch/eve_launch.py rename to src/perception/camera_object_detection/launch/include/pretrained_yolov8.launch.py index 94ac35df..9403139f --- a/src/perception/camera_object_detection/launch/eve_launch.py +++ b/src/perception/camera_object_detection/launch/include/pretrained_yolov8.launch.py @@ -5,14 +5,12 @@ def generate_launch_description(): - ld = LaunchDescription() config = os.path.join( get_package_share_directory('camera_object_detection'), 'config', 'eve_config.yaml' ) - # nodes left_camera_object_detection_node = Node( package='camera_object_detection', executable='camera_object_detection_node', @@ -33,10 +31,9 @@ def generate_launch_description(): name='right_camera_object_detection_node', parameters=[config] ) - - # finalize - ld.add_action(left_camera_object_detection_node) - ld.add_action(center_camera_object_detection_node) - ld.add_action(right_camera_object_detection_node) - - return ld + + return LaunchDescription([ + left_camera_object_detection_node, + center_camera_object_detection_node, + right_camera_object_detection_node, + ]) diff --git a/src/perception/camera_object_detection/launch/traffic_light_launch.py b/src/perception/camera_object_detection/launch/include/traffic_light.launch.py similarity index 82% rename from src/perception/camera_object_detection/launch/traffic_light_launch.py rename to src/perception/camera_object_detection/launch/include/traffic_light.launch.py index f59035de..234844b8 100755 --- a/src/perception/camera_object_detection/launch/traffic_light_launch.py +++ b/src/perception/camera_object_detection/launch/include/traffic_light.launch.py @@ -5,14 +5,12 @@ def generate_launch_description(): - ld = LaunchDescription() config = os.path.join( get_package_share_directory('camera_object_detection'), 'config', 'traffic_light_config.yaml' ) - # nodes camera_object_detection_node = Node( package='camera_object_detection', executable='camera_object_detection_node', @@ -20,7 +18,4 @@ def generate_launch_description(): parameters=[config] ) - # finalize - ld.add_action(camera_object_detection_node) - - return ld + return LaunchDescription([camera_object_detection_node]) diff --git a/src/perception/camera_object_detection/launch/nuscenes_launch.py b/src/perception/camera_object_detection/launch/nuscenes.launch.py similarity index 87% rename from src/perception/camera_object_detection/launch/nuscenes_launch.py rename to src/perception/camera_object_detection/launch/nuscenes.launch.py index 7a366260..878e34ef 100755 --- a/src/perception/camera_object_detection/launch/nuscenes_launch.py +++ b/src/perception/camera_object_detection/launch/nuscenes.launch.py @@ -12,7 +12,6 @@ def generate_launch_description(): 'nuscenes_config.yaml' ) - # nodes camera_object_detection_node = Node( package='camera_object_detection', executable='camera_object_detection_node', @@ -21,7 +20,5 @@ def generate_launch_description(): arguments=['--ros-args', '--log-level', 'info'] ) - # finalize - ld.add_action(camera_object_detection_node) - return ld + return LaunchDescription([camera_object_detection_node]) From 067805a8024ba91290ab1029ad176710c79655a4 Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Fri, 8 Mar 2024 02:18:27 +0000 Subject: [PATCH 09/15] Update file names --- .../launch/eve.launch.py | 17 ++--------------- src/perception/camera_object_detection/setup.py | 3 ++- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/perception/camera_object_detection/launch/eve.launch.py b/src/perception/camera_object_detection/launch/eve.launch.py index a39c0ef2..a0027cf8 100755 --- a/src/perception/camera_object_detection/launch/eve.launch.py +++ b/src/perception/camera_object_detection/launch/eve.launch.py @@ -12,16 +12,11 @@ def generate_launch_description(): launch_traffic_light_arg = DeclareLaunchArgument('launch_traffic_light', default_value=launch_traffic_light, description='Launch traffic light detection') - launch_traffic_sign = LaunchConfiguration('launch_traffic_sign', default=True) - launch_traffic_sign_arg = DeclareLaunchArgument('launch_traffic_sign', - default_value=launch_traffic_sign, - description='Launch traffic sign detection') - launch_args = [launch_traffic_light_arg, - launch_traffic_sign_arg] + launch_args = [launch_traffic_light_arg] camera_object_detection_launch_include_dir = os.path.join( - get_package_share_directory('carter_navigation'), 'launch', 'include') + get_package_share_directory('camera_object_detection'), 'launch', 'include') pretrained_yolov8_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource( @@ -35,15 +30,7 @@ def generate_launch_description(): 'launch_traffic_light', 'True') ) - traffic_sign_launch = IncludeLaunchDescription( - PythonLaunchDescriptionSource( - [camera_object_detection_launch_include_dir, '/traffic_sign.launch.py']), - condition=LaunchConfigurationEquals( - 'launch_traffic_sign', 'True') - ) - return LaunchDescription(launch_args + [ pretrained_yolov8_launch, traffic_light_launch, - traffic_sign_launch ]) diff --git a/src/perception/camera_object_detection/setup.py b/src/perception/camera_object_detection/setup.py index 7ba35c15..c9665f79 100755 --- a/src/perception/camera_object_detection/setup.py +++ b/src/perception/camera_object_detection/setup.py @@ -12,7 +12,8 @@ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), ('share/' + package_name, ['package.xml']), - (os.path.join('share', package_name, 'launch'), glob('launch/*.py')), + (os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')), + (os.path.join('share', package_name, 'launch', 'include'), glob('launch/include/*.launch.py')), (os.path.join('share', package_name, 'config'), glob('config/*.yaml')), ], install_requires=['setuptools'], From 5679d63459ca7562dd175f9528f81839c6b48306 Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Fri, 8 Mar 2024 02:36:29 +0000 Subject: [PATCH 10/15] Format code --- .../yolov8_detection.py | 74 +++++++++---------- .../launch/nuscenes.launch.py | 1 - 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py b/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py index ea950400..05ceb431 100755 --- a/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py +++ b/src/perception/camera_object_detection/camera_object_detection/yolov8_detection.py @@ -43,14 +43,13 @@ def __init__(self): self.camera_topic = self.get_parameter("camera_topic").value self.publish_vis_topic = self.get_parameter("publish_vis_topic").value - self.publish_detection_topic = self.get_parameter( - "publish_detection_topic").value + self.publish_detection_topic = self.get_parameter("publish_detection_topic").value self.model_path = self.get_parameter("model_path").value self.image_size = self.get_parameter("image_size").value self.compressed = self.get_parameter("compressed").value self.crop_mode = self.get_parameter("crop_mode").value self.save_detections = bool(self.get_parameter("save_detections").value) - self.counter = 0 # For saving detections + self.counter = 0 # For saving detections if self.save_detections: if not os.path.exists("detections"): os.makedirs("detections") @@ -68,13 +67,12 @@ def __init__(self): depth=10, ), ) - + self.orig_image_width = None self.orig_image_height = None # set device - self.device = torch.device( - "cuda" if torch.cuda.is_available() else "cpu") + self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") if torch.cuda.is_available(): self.get_logger().info("Using GPU for inference") else: @@ -84,32 +82,29 @@ def __init__(self): self.cv_bridge = CvBridge() # load yolov8 model - self.model = AutoBackend( - self.model_path, device=self.device, dnn=False, fp16=False) + self.model = AutoBackend(self.model_path, device=self.device, dnn=False, fp16=False) - self.names = self.model.module.names if hasattr( - self.model, "module") else self.model.names + self.names = self.model.module.names if hasattr(self.model, "module") else self.model.names self.stride = int(self.model.stride) # setup vis publishers - self.vis_publisher = self.create_publisher( - Image, self.publish_vis_topic, 10) + self.vis_publisher = self.create_publisher(Image, self.publish_vis_topic, 10) self.detection_publisher = self.create_publisher( - Detection2DArray, self.publish_detection_topic, 10) + Detection2DArray, self.publish_detection_topic, 10 + ) self.get_logger().info( - f"Successfully created node listening on camera topic: {self.camera_topic}...") + f"Successfully created node listening on camera topic: {self.camera_topic}..." + ) def crop_image(self, cv_image): if self.crop_mode == "LetterBox": - img = LetterBox(self.image_size, stride=self.stride)( - image=cv_image) + img = LetterBox(self.image_size, stride=self.stride)(image=cv_image) elif self.crop_mode == "CenterCrop": img = CenterCrop(self.image_size)(cv_image) else: - raise Exception( - "Invalid crop mode, please choose either 'LetterBox' or 'CenterCrop'!") + raise Exception("Invalid crop mode, please choose either 'LetterBox' or 'CenterCrop'!") return img @@ -117,33 +112,37 @@ def convert_bboxes_to_orig_frame(self, bbox): """ Converts bounding box coordinates from the scaled image frame back to the original image frame. - This function takes into account the original image dimensions and the scaling method used - (either "LetterBox" or "CenterCrop") to accurately map the bounding box coordinates back to + This function takes into account the original image dimensions and the scaling method used + (either "LetterBox" or "CenterCrop") to accurately map the bounding box coordinates back to their original positions in the original image. Parameters: - bbox (list): A list containing the bounding box coordinates in the format [x1, y1, w1, h1] + bbox (list): A list containing the bounding box coordinates in the format [x1, y1, w1, h1] in the scaled image frame. Returns: - list: A list containing the bounding box coordinates in the format [x1, y1, w1, h1] + list: A list containing the bounding box coordinates in the format [x1, y1, w1, h1] in the original image frame. - + """ width_scale = self.orig_image_width / self.image_size height_scale = self.orig_image_height / self.image_size if self.crop_mode == "LetterBox": translation = (self.image_size - self.orig_image_height / width_scale) / 2 - return [bbox[0] * width_scale, - (bbox[1] - translation) * width_scale, - bbox[2] * width_scale, - bbox[3] * width_scale] + return [ + bbox[0] * width_scale, + (bbox[1] - translation) * width_scale, + bbox[2] * width_scale, + bbox[3] * width_scale, + ] elif self.crop_mode == "CenterCrop": translation = (self.orig_image_width / height_scale - self.image_size) / 2 - return [(bbox[0] + translation) * height_scale, - bbox[1] * height_scale, - bbox[2] * height_scale, - bbox[3] * height_scale] + return [ + (bbox[0] + translation) * height_scale, + bbox[1] * height_scale, + bbox[2] * height_scale, + bbox[3] * height_scale, + ] def crop_and_convert_to_tensor(self, cv_image): """ @@ -232,7 +231,7 @@ def publish_detections(self, detections, msg, feed): def image_callback(self, msg): self.get_logger().debug("Received image") - if (self.orig_image_width is None): + if self.orig_image_width is None: self.orig_image_width = msg.width self.orig_image_height = msg.height @@ -246,8 +245,7 @@ def image_callback(self, msg): cv_image = cv2.imdecode(np_arr, cv2.IMREAD_COLOR) else: try: - cv_image = self.cv_bridge.imgmsg_to_cv2( - image, desired_encoding="passthrough") + cv_image = self.cv_bridge.imgmsg_to_cv2(image, desired_encoding="passthrough") except CvBridgeError as e: self.get_logger().error(str(e)) return @@ -288,20 +286,20 @@ def image_callback(self, msg): line_width=self.line_thickness, example=str(self.names), ) - (detections, annotated_img) = self.postprocess_detections( - detections, annotator) + (detections, annotated_img) = self.postprocess_detections(detections, annotator) # Currently we support a single camera so we pass an empty string feed = "" self.publish_vis(annotated_img, msg, feed) self.publish_detections(detections, msg, feed) - + if self.save_detections: cv2.imwrite(f"detections/{self.counter}.jpg", annotated_img) self.counter += 1 self.get_logger().info( - f"Finished in: {time.time() - startTime}, {1/(time.time() - startTime)} Hz") + f"Finished in: {time.time() - startTime}, {1/(time.time() - startTime)} Hz" + ) def main(args=None): diff --git a/src/perception/camera_object_detection/launch/nuscenes.launch.py b/src/perception/camera_object_detection/launch/nuscenes.launch.py index 878e34ef..faff24b6 100755 --- a/src/perception/camera_object_detection/launch/nuscenes.launch.py +++ b/src/perception/camera_object_detection/launch/nuscenes.launch.py @@ -20,5 +20,4 @@ def generate_launch_description(): arguments=['--ros-args', '--log-level', 'info'] ) - return LaunchDescription([camera_object_detection_node]) From db6f04ea774ab9019a6d80666a4f4fe3fda839d9 Mon Sep 17 00:00:00 2001 From: Steven Gong Date: Fri, 8 Mar 2024 02:39:25 +0000 Subject: [PATCH 11/15] Fix more formatting --- .../launch/eve.launch.py | 35 +++++++++------- .../include/pretrained_yolov8.launch.py | 42 +++++++++---------- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/perception/camera_object_detection/launch/eve.launch.py b/src/perception/camera_object_detection/launch/eve.launch.py index a0027cf8..53c3eb08 100755 --- a/src/perception/camera_object_detection/launch/eve.launch.py +++ b/src/perception/camera_object_detection/launch/eve.launch.py @@ -8,29 +8,36 @@ def generate_launch_description(): - launch_traffic_light = LaunchConfiguration('launch_traffic_light', default=True) - launch_traffic_light_arg = DeclareLaunchArgument('launch_traffic_light', - default_value=launch_traffic_light, - description='Launch traffic light detection') - + launch_traffic_light = LaunchConfiguration("launch_traffic_light", default=True) + launch_traffic_light_arg = DeclareLaunchArgument( + "launch_traffic_light", + default_value=launch_traffic_light, + description="Launch traffic light detection", + ) + launch_args = [launch_traffic_light_arg] camera_object_detection_launch_include_dir = os.path.join( - get_package_share_directory('camera_object_detection'), 'launch', 'include') + get_package_share_directory("camera_object_detection"), "launch", "include" + ) pretrained_yolov8_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource( - [camera_object_detection_launch_include_dir, '/pretrained_yolov8.launch.py']), + [camera_object_detection_launch_include_dir, "/pretrained_yolov8.launch.py"] + ), ) traffic_light_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource( - [camera_object_detection_launch_include_dir, '/traffic_light.launch.py']), - condition=LaunchConfigurationEquals( - 'launch_traffic_light', 'True') + [camera_object_detection_launch_include_dir, "/traffic_light.launch.py"] + ), + condition=LaunchConfigurationEquals("launch_traffic_light", "True"), ) - return LaunchDescription(launch_args + [ - pretrained_yolov8_launch, - traffic_light_launch, - ]) + return LaunchDescription( + launch_args + + [ + pretrained_yolov8_launch, + traffic_light_launch, + ] + ) diff --git a/src/perception/camera_object_detection/launch/include/pretrained_yolov8.launch.py b/src/perception/camera_object_detection/launch/include/pretrained_yolov8.launch.py index 9403139f..13096462 100644 --- a/src/perception/camera_object_detection/launch/include/pretrained_yolov8.launch.py +++ b/src/perception/camera_object_detection/launch/include/pretrained_yolov8.launch.py @@ -6,34 +6,34 @@ def generate_launch_description(): config = os.path.join( - get_package_share_directory('camera_object_detection'), - 'config', - 'eve_config.yaml' + get_package_share_directory("camera_object_detection"), "config", "eve_config.yaml" ) left_camera_object_detection_node = Node( - package='camera_object_detection', - executable='camera_object_detection_node', - name='left_camera_object_detection_node', - parameters=[config] + package="camera_object_detection", + executable="camera_object_detection_node", + name="left_camera_object_detection_node", + parameters=[config], ) center_camera_object_detection_node = Node( - package='camera_object_detection', - executable='camera_object_detection_node', - name='center_camera_object_detection_node', - parameters=[config] + package="camera_object_detection", + executable="camera_object_detection_node", + name="center_camera_object_detection_node", + parameters=[config], ) right_camera_object_detection_node = Node( - package='camera_object_detection', - executable='camera_object_detection_node', - name='right_camera_object_detection_node', - parameters=[config] + package="camera_object_detection", + executable="camera_object_detection_node", + name="right_camera_object_detection_node", + parameters=[config], + ) + + return LaunchDescription( + [ + left_camera_object_detection_node, + center_camera_object_detection_node, + right_camera_object_detection_node, + ] ) - - return LaunchDescription([ - left_camera_object_detection_node, - center_camera_object_detection_node, - right_camera_object_detection_node, - ]) From 56d5128c886d08507ef21cc1ab576cacb2227412 Mon Sep 17 00:00:00 2001 From: Mark Chiu Date: Thu, 7 Mar 2024 23:54:56 -0500 Subject: [PATCH 12/15] Add traffic sign launch file (#83) * initial commit * Revert unecessary changes * Remove model data * Add CenterCrop and modify training parameters * Remove build and install folder * Uncommit watod-config * Change traffic signs config * Uncommit changes * Uncommit changes launch files * Remove train + restore detection * Fix lint errors * Fix lint errors 2 * Remove remnant of perception traffic signs node * Update launch file * Restore to medium size * Remove redundant code * Add back line --------- Co-authored-by: Steven Gong --- .../traffic_sign_detection.Dockerfile | 55 ------------------- .../docker-compose.perception.yaml | 9 --- modules/docker-compose.perception.yaml | 13 +---- .../config/traffic_signs_config.yaml | 9 +++ .../launch/eve.launch.py | 16 +++++- .../launch/include/traffic_signs.launch.py | 21 +++++++ .../traffic_sign_detection/CMakeLists.txt | 14 ----- .../traffic_sign_detection/package.xml | 16 ------ watod_scripts/watod-setup-env.sh | 2 - 9 files changed, 47 insertions(+), 108 deletions(-) delete mode 100644 docker/perception/traffic_sign_detection/traffic_sign_detection.Dockerfile create mode 100644 src/perception/camera_object_detection/config/traffic_signs_config.yaml create mode 100644 src/perception/camera_object_detection/launch/include/traffic_signs.launch.py delete mode 100644 src/perception/traffic_sign_detection/CMakeLists.txt delete mode 100644 src/perception/traffic_sign_detection/package.xml diff --git a/docker/perception/traffic_sign_detection/traffic_sign_detection.Dockerfile b/docker/perception/traffic_sign_detection/traffic_sign_detection.Dockerfile deleted file mode 100644 index a07d0507..00000000 --- a/docker/perception/traffic_sign_detection/traffic_sign_detection.Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -ARG BASE_IMAGE=ghcr.io/watonomous/wato_monorepo/base:humble-ubuntu22.04 - -################################ Source ################################ -FROM ${BASE_IMAGE} as source - -WORKDIR ${AMENT_WS}/src - -# Copy in source code -COPY src/perception/traffic_sign_detection traffic_sign_detection -COPY src/wato_msgs/sample_msgs sample_msgs - -# Scan for rosdeps -RUN apt-get -qq update && rosdep update && \ - rosdep install --from-paths . --ignore-src -r -s \ - | grep 'apt-get install' \ - | awk '{print $3}' \ - | sort > /tmp/colcon_install_list - -################################# Dependencies ################################ -FROM ${BASE_IMAGE} as dependencies - -# Install Rosdep requirements -COPY --from=source /tmp/colcon_install_list /tmp/colcon_install_list -RUN apt-fast install -qq -y --no-install-recommends $(cat /tmp/colcon_install_list) - -# Copy in source code from source stage -WORKDIR ${AMENT_WS} -COPY --from=source ${AMENT_WS}/src src - -# Dependency Cleanup -WORKDIR / -RUN apt-get -qq autoremove -y && apt-get -qq autoclean && apt-get -qq clean && \ - rm -rf /root/* /root/.ros /tmp/* /var/lib/apt/lists/* /usr/share/doc/* - -################################ Build ################################ -FROM dependencies as build - -# Build ROS2 packages -WORKDIR ${AMENT_WS} -RUN . /opt/ros/$ROS_DISTRO/setup.sh && \ - colcon build \ - --cmake-args -DCMAKE_BUILD_TYPE=Release - -# Entrypoint will run before any CMD on launch. Sources ~/opt//setup.bash and ~/ament_ws/install/setup.bash -COPY docker/wato_ros_entrypoint.sh ${AMENT_WS}/wato_ros_entrypoint.sh -ENTRYPOINT ["./wato_ros_entrypoint.sh"] - -################################ Prod ################################ -FROM build as deploy - -# Source Cleanup and Security Setup -RUN chown -R $USER:$USER ${AMENT_WS} -RUN rm -rf src/* - -USER ${USER} diff --git a/modules/dev_overrides/docker-compose.perception.yaml b/modules/dev_overrides/docker-compose.perception.yaml index 07e28ec2..ee5913f9 100644 --- a/modules/dev_overrides/docker-compose.perception.yaml +++ b/modules/dev_overrides/docker-compose.perception.yaml @@ -32,15 +32,6 @@ services: volumes: - ${MONO_DIR}/src/perception/lidar_object_detection:/home/bolty/ament_ws/src/lidar_object_detection - traffic_sign_detection: - <<: *fixuid - extends: - file: ../docker-compose.perception.yaml - service: traffic_sign_detection - command: tail -F anything - volumes: - - ${MONO_DIR}/src/perception/traffic_sign_detection:/home/bolty/ament_ws/src/traffic_sign_detection - semantic_segmentation: <<: *fixuid extends: diff --git a/modules/docker-compose.perception.yaml b/modules/docker-compose.perception.yaml index 8c806df9..75d9d165 100644 --- a/modules/docker-compose.perception.yaml +++ b/modules/docker-compose.perception.yaml @@ -21,6 +21,7 @@ services: - "${PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE:?}:build_main" target: deploy image: "${PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE:?}:${TAG}" + shm_size: 8G deploy: resources: reservations: @@ -32,6 +33,7 @@ services: volumes: - /mnt/wato-drive2/perception_models/yolov8m.pt:/perception_models/yolov8m.pt - /mnt/wato-drive2/perception_models/traffic_light.pt:/perception_models/traffic_light.pt + - /mnt/wato-drive2/perception_models/traffic_signs_v0.pt:/perception_models/traffic_signs_v1.pt lidar_object_detection: build: @@ -44,17 +46,6 @@ services: image: "${PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE}:${TAG}" command: /bin/bash -c "ros2 launch lidar_object_detection lidar_object_detection.launch.py" - traffic_sign_detection: - build: - context: .. - dockerfile: docker/perception/traffic_sign_detection/traffic_sign_detection.Dockerfile - cache_from: - - "${PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE}:build_${TAG}" - - "${PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE}:build_main" - target: deploy - image: "${PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE}:${TAG}" - command: /bin/bash -c "ros2 launch traffic_sign_detection traffic_sign_detection.launch.py" - semantic_segmentation: build: context: .. diff --git a/src/perception/camera_object_detection/config/traffic_signs_config.yaml b/src/perception/camera_object_detection/config/traffic_signs_config.yaml new file mode 100644 index 00000000..8a143a77 --- /dev/null +++ b/src/perception/camera_object_detection/config/traffic_signs_config.yaml @@ -0,0 +1,9 @@ +traffic_signs_node: + ros__parameters: + camera_topic: /camera/left/image_color + publish_vis_topic: /traffic_signs_viz + publish_detection_topic: /traffic_signs + model_path: /perception_models/traffic_signs_v1.pt + crop_mode: CenterCrop + image_size: 1024 + save_detections: false diff --git a/src/perception/camera_object_detection/launch/eve.launch.py b/src/perception/camera_object_detection/launch/eve.launch.py index 53c3eb08..9ff4992e 100755 --- a/src/perception/camera_object_detection/launch/eve.launch.py +++ b/src/perception/camera_object_detection/launch/eve.launch.py @@ -14,8 +14,14 @@ def generate_launch_description(): default_value=launch_traffic_light, description="Launch traffic light detection", ) + launch_traffic_signs = LaunchConfiguration("launch_traffic_signs", default=True) + launch_traffic_signs_arg = DeclareLaunchArgument( + "launch_traffic_signs", + default_value=launch_traffic_signs, + description="Launch traffic signs detection", + ) - launch_args = [launch_traffic_light_arg] + launch_args = [launch_traffic_light_arg, launch_traffic_signs_arg] camera_object_detection_launch_include_dir = os.path.join( get_package_share_directory("camera_object_detection"), "launch", "include" @@ -34,10 +40,18 @@ def generate_launch_description(): condition=LaunchConfigurationEquals("launch_traffic_light", "True"), ) + traffic_signs_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [camera_object_detection_launch_include_dir, "/traffic_signs.launch.py"] + ), + condition=LaunchConfigurationEquals("launch_traffic_signs", "True"), + ) + return LaunchDescription( launch_args + [ pretrained_yolov8_launch, traffic_light_launch, + traffic_signs_launch, ] ) diff --git a/src/perception/camera_object_detection/launch/include/traffic_signs.launch.py b/src/perception/camera_object_detection/launch/include/traffic_signs.launch.py new file mode 100644 index 00000000..cdb0134f --- /dev/null +++ b/src/perception/camera_object_detection/launch/include/traffic_signs.launch.py @@ -0,0 +1,21 @@ +from launch import LaunchDescription +from launch_ros.actions import Node +from ament_index_python.packages import get_package_share_directory +import os + + +def generate_launch_description(): + config = os.path.join( + get_package_share_directory('camera_object_detection'), + 'config', + 'traffic_signs_config.yaml' + ) + + camera_object_detection_node = Node( + package='camera_object_detection', + executable='camera_object_detection_node', + name='traffic_signs_node', + parameters=[config] + ) + + return LaunchDescription([camera_object_detection_node]) diff --git a/src/perception/traffic_sign_detection/CMakeLists.txt b/src/perception/traffic_sign_detection/CMakeLists.txt deleted file mode 100644 index b968c4cf..00000000 --- a/src/perception/traffic_sign_detection/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -cmake_minimum_required(VERSION 3.8) -project(traffic_sign_detection) - -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) -endif() - -# find dependencies -find_package(ament_cmake REQUIRED) -# uncomment the following section in order to fill in -# further dependencies manually. -# find_package( REQUIRED) - -ament_package() diff --git a/src/perception/traffic_sign_detection/package.xml b/src/perception/traffic_sign_detection/package.xml deleted file mode 100644 index 48d6de51..00000000 --- a/src/perception/traffic_sign_detection/package.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - traffic_sign_detection - 0.0.0 - TODO: Package description - bolty - TODO: License declaration - - ament_cmake - - - - ament_cmake - - diff --git a/watod_scripts/watod-setup-env.sh b/watod_scripts/watod-setup-env.sh index e8b7227b..029e9233 100755 --- a/watod_scripts/watod-setup-env.sh +++ b/watod_scripts/watod-setup-env.sh @@ -69,7 +69,6 @@ INFRASTRUCTURE_FOXGLOVE_IMAGE=${DATA_STREAM_IMAGE:-"$REGISTRY_URL/infrastructure PERCEPTION_RADAR_OBJECT_DETECTION_IMAGE=${PERCEPTION_RADAR_OBJECT_DETECTION_IMAGE:-"$REGISTRY_URL/perception/radar_object_detection"} PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE=${PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE:-"$REGISTRY_URL/perception/lidar_object_detection"} PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE=${PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE:-"$REGISTRY_URL/perception/camera_object_detection"} -PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE=${PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE:-"$REGISTRY_URL/perception/traffic_sign_detection"} PERCEPTION_LANE_DETECTION_IMAGE=${PERCEPTION_LANE_DETECTION_IMAGE:-"$REGISTRY_URL/perception/lane_detection"} PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE=${PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE:-"$REGISTRY_URL/perception/semantic_segmentation"} PERCEPTION_TRACKING_IMAGE=${PERCEPTION_TRACKING_IMAGE:-"$REGISTRY_URL/perception/tracking"} @@ -164,7 +163,6 @@ echo "INFRASTRUCTURE_FOXGLOVE_IMAGE=$INFRASTRUCTURE_FOXGLOVE_IMAGE" >> "$MODULES echo "PERCEPTION_RADAR_OBJECT_DETECTION_IMAGE=$PERCEPTION_RADAR_OBJECT_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE=$PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE=$PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE" >> "$MODULES_DIR/.env" -echo "PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE=$PERCEPTION_TRAFFIC_SIGN_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_LANE_DETECTION_IMAGE=$PERCEPTION_LANE_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE=$PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_TRACKING_IMAGE=$PERCEPTION_TRACKING_IMAGE" >> "$MODULES_DIR/.env" From aee5e7def1c1d6e694f84db05d8fe7210c3697e8 Mon Sep 17 00:00:00 2001 From: Eddy Zhou <71026430+Edwardius@users.noreply.github.com> Date: Fri, 8 Mar 2024 19:56:17 +0900 Subject: [PATCH 13/15] pulls build stage when we are in develop mode (#90) * pulls build stage when we are in develop mode * auto linter is not running automatically * auto linter label actually causes a race condition to occur * theres a bug here where if you run autolinter without any errors branch protection doesn't let you through --- .github/workflows/linting_auto.yml | 3 ++- modules/dev_overrides/docker-compose.action.yaml | 4 ++++ modules/dev_overrides/docker-compose.interfacing.yaml | 2 ++ modules/dev_overrides/docker-compose.perception.yaml | 6 ++++++ modules/dev_overrides/docker-compose.samples.yaml | 9 +++++++++ modules/dev_overrides/docker-compose.world_modeling.yaml | 5 +++++ 6 files changed, 28 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linting_auto.yml b/.github/workflows/linting_auto.yml index a02b3b0c..a2b7646f 100644 --- a/.github/workflows/linting_auto.yml +++ b/.github/workflows/linting_auto.yml @@ -8,6 +8,7 @@ on: branches: - main types: + - unlabeled - labeled - synchronize @@ -51,4 +52,4 @@ jobs: repo: context.repo.repo, issue_number: context.issue.number, name: 'auto-lint' - }); \ No newline at end of file + }); diff --git a/modules/dev_overrides/docker-compose.action.yaml b/modules/dev_overrides/docker-compose.action.yaml index 1318b6bc..1984e6db 100644 --- a/modules/dev_overrides/docker-compose.action.yaml +++ b/modules/dev_overrides/docker-compose.action.yaml @@ -10,6 +10,7 @@ services: extends: file: ../docker-compose.action.yaml service: global_planning + image: "${ACTION_GLOBAL_PLANNING_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/action/global_planning:/home/ament_ws/src/global_planning @@ -19,6 +20,7 @@ services: extends: file: ../docker-compose.action.yaml service: behaviour_planning + image: "${ACTION_BEHAVIOUR_PLANNING_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/action/behaviour_planning:/home/ament_ws/src/behaviour_planning @@ -28,6 +30,7 @@ services: extends: file: ../docker-compose.action.yaml service: local_planning + image: "${ACTION_LOCAL_PLANNING_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/action/local_planning:/home/ament_ws/src/local_planning @@ -37,6 +40,7 @@ services: extends: file: ../docker-compose.action.yaml service: model_predictive_control + image: "${ACTION_MPC_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/action/model_predictive_control:/home/ament_ws/src/model_predictive_control \ No newline at end of file diff --git a/modules/dev_overrides/docker-compose.interfacing.yaml b/modules/dev_overrides/docker-compose.interfacing.yaml index 503469d9..12a5db5b 100644 --- a/modules/dev_overrides/docker-compose.interfacing.yaml +++ b/modules/dev_overrides/docker-compose.interfacing.yaml @@ -10,6 +10,7 @@ services: extends: file: ../docker-compose.interfacing.yaml service: sensor_interfacing + image: "${INTERFACING_SENSOR_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/sensor_interfacing:/home/bolty/ament_ws/src/sensor_interfacing @@ -19,6 +20,7 @@ services: extends: file: ../docker-compose.interfacing.yaml service: can_interfacing + image: "${INTERFACING_CAN_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/can_interfacing:/home/bolty/ament_ws/src/can_interfacing diff --git a/modules/dev_overrides/docker-compose.perception.yaml b/modules/dev_overrides/docker-compose.perception.yaml index ee5913f9..3a1a522d 100644 --- a/modules/dev_overrides/docker-compose.perception.yaml +++ b/modules/dev_overrides/docker-compose.perception.yaml @@ -10,6 +10,7 @@ services: extends: file: ../docker-compose.perception.yaml service: radar_object_detection + image: "${PERCEPTION_RADAR_OBJECT_DETECTION_IMAGE:?}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/perception/radar_object_detection:/home/bolty/ament_ws/src/radar_object_detection @@ -19,6 +20,7 @@ services: extends: file: ../docker-compose.perception.yaml service: camera_object_detection + image: "${PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE:?}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/perception/camera_object_detection:/home/bolty/ament_ws/src/camera_object_detection @@ -28,6 +30,7 @@ services: extends: file: ../docker-compose.perception.yaml service: lidar_object_detection + image: "${PERCEPTION_LIDAR_OBJECT_DETECTION_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/perception/lidar_object_detection:/home/bolty/ament_ws/src/lidar_object_detection @@ -37,6 +40,7 @@ services: extends: file: ../docker-compose.perception.yaml service: semantic_segmentation + image: "${PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/perception/semantic_segmentation:/home/bolty/ament_ws/src/semantic_segmentation @@ -46,6 +50,7 @@ services: extends: file: ../docker-compose.perception.yaml service: lane_detection + image: "${PERCEPTION_LANE_DETECTION_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/perception/lane_detection:/home/bolty/ament_ws/src/lane_detection @@ -55,6 +60,7 @@ services: extends: file: ../docker-compose.perception.yaml service: tracking + image: "${PERCEPTION_TRACKING_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/perception/tracking:/home/bolty/ament_ws/src/tracking diff --git a/modules/dev_overrides/docker-compose.samples.yaml b/modules/dev_overrides/docker-compose.samples.yaml index 2d49b7bf..335da171 100644 --- a/modules/dev_overrides/docker-compose.samples.yaml +++ b/modules/dev_overrides/docker-compose.samples.yaml @@ -10,6 +10,7 @@ services: extends: file: ../docker-compose.samples.yaml service: cpp_aggregator + image: "${SAMPLES_CPP_AGGREGATOR_IMAGE:?}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/samples/cpp/aggregator:/home/bolty/ament_ws/src/aggregator @@ -19,6 +20,8 @@ services: # extends: # file: ../docker-compose.samples.yaml # service: py_aggregator + # image: "${SAMPLES_PYTHON_AGGREGATOR_IMAGE:?}:build_${TAG}" + # command: tail -F anything # volumes: # - ${MONO_DIR}/src/samples/python/aggregator:/home/bolty/ament_ws/src/aggregator @@ -27,6 +30,8 @@ services: # extends: # file: ../docker-compose.samples.yaml # service: cpp_producer + # image: "${SAMPLES_CPP_PRODUCER_IMAGE:?}:build_${TAG}" + # command: tail -F anything # volumes: # - ${MONO_DIR}/src/samples/cpp/producer:/home/bolty/ament_ws/src/producer @@ -35,6 +40,7 @@ services: extends: file: ../docker-compose.samples.yaml service: py_producer + image: "${SAMPLES_PYTHON_PRODUCER_IMAGE:?}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/samples/python/producer:/home/bolty/ament_ws/src/producer @@ -44,6 +50,8 @@ services: # extends: # file: ../docker-compose.samples.yaml # service: cpp_transformer + # image: "${SAMPLES_CPP_TRANSFORMER_IMAGE:?}:build_${TAG}" + # command: tail -F anything # volumes: # - ${MONO_DIR}/src/samples/cpp/transformer:/home/bolty/ament_ws/src/transformer @@ -52,6 +60,7 @@ services: extends: file: ../docker-compose.samples.yaml service: py_transformer + image: "${SAMPLES_PYTHON_TRANSFORMER_IMAGE:?}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/samples/python/transformer:/home/bolty/ament_ws/src/transformer diff --git a/modules/dev_overrides/docker-compose.world_modeling.yaml b/modules/dev_overrides/docker-compose.world_modeling.yaml index 67b03241..7682c63a 100644 --- a/modules/dev_overrides/docker-compose.world_modeling.yaml +++ b/modules/dev_overrides/docker-compose.world_modeling.yaml @@ -10,6 +10,7 @@ services: extends: file: ../docker-compose.world_modeling.yaml service: hd_map + image: "${WORLD_MODELING_HD_MAP_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/world_modeling:/home/ament_ws/src/hd_map @@ -19,6 +20,7 @@ services: extends: file: ../docker-compose.world_modeling.yaml service: localization + image: "${WORLD_MODELING_LOCALIZATION_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/world_modeling:/home/ament_ws/src/localization @@ -28,6 +30,7 @@ services: extends: file: ../docker-compose.world_modeling.yaml service: occupancy + image: "${WORLD_MODELING_OCCUPANCY_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/world_modeling:/home/ament_ws/src/occupancy @@ -37,6 +40,7 @@ services: extends: file: ../docker-compose.world_modeling.yaml service: occupancy_segmentation + image: "${WORLD_MODELING_OCCUPANCY_SEGMENTATION_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/world_modeling:/home/ament_ws/src/occupancy_segmentation @@ -46,6 +50,7 @@ services: extends: file: ../docker-compose.world_modeling.yaml service: motion_forecasting + image: "${WORLD_MODELING_MOTION_FORECASTING_IMAGE}:build_${TAG}" command: tail -F anything volumes: - ${MONO_DIR}/src/world_modeling:/home/ament_ws/src/motion_forecasting From 46df00e2bddc0065952e463c947828a3a6e30219 Mon Sep 17 00:00:00 2001 From: Justin Leung Date: Thu, 21 Mar 2024 06:39:42 +0000 Subject: [PATCH 14/15] Add depth estimation node starter code --- .../depth_estimation.Dockerfile | 54 +++++++++++++++++++ .../docker-compose.perception.yaml | 10 ++++ modules/docker-compose.perception.yaml | 11 ++++ .../depth_estimation/CMakeLists.txt | 36 +++++++++++++ .../depth_estimation/config/config.yaml | 5 ++ .../include/depth_estimation_node.hpp | 22 ++++++++ .../depth_estimation/launch/eve.launch.py | 25 +++++++++ src/perception/depth_estimation/package.xml | 16 ++++++ .../src/depth_estimation_node.cpp | 39 ++++++++++++++ watod_scripts/watod-setup-env.sh | 2 + 10 files changed, 220 insertions(+) create mode 100644 docker/perception/depth_estimation/depth_estimation.Dockerfile create mode 100644 src/perception/depth_estimation/CMakeLists.txt create mode 100644 src/perception/depth_estimation/config/config.yaml create mode 100644 src/perception/depth_estimation/include/depth_estimation_node.hpp create mode 100644 src/perception/depth_estimation/launch/eve.launch.py create mode 100644 src/perception/depth_estimation/package.xml create mode 100644 src/perception/depth_estimation/src/depth_estimation_node.cpp diff --git a/docker/perception/depth_estimation/depth_estimation.Dockerfile b/docker/perception/depth_estimation/depth_estimation.Dockerfile new file mode 100644 index 00000000..d51497ae --- /dev/null +++ b/docker/perception/depth_estimation/depth_estimation.Dockerfile @@ -0,0 +1,54 @@ +ARG BASE_IMAGE=ghcr.io/watonomous/wato_monorepo/base:humble-ubuntu22.04 + +################################ Source ################################ +FROM ${BASE_IMAGE} as source + +WORKDIR ${AMENT_WS}/src + +# Copy in source code +COPY src/perception/depth_estimation depth_estimation + +# Scan for rosdeps +RUN apt-get -qq update && rosdep update && \ + rosdep install --from-paths . --ignore-src -r -s \ + | grep 'apt-get install' \ + | awk '{print $3}' \ + | sort > /tmp/colcon_install_list + +################################# Dependencies ################################ +FROM ${BASE_IMAGE} as dependencies + +# Install Rosdep requirements +COPY --from=source /tmp/colcon_install_list /tmp/colcon_install_list +RUN apt-fast install -qq -y --no-install-recommends $(cat /tmp/colcon_install_list) + +# Copy in source code from source stage +WORKDIR ${AMENT_WS} +COPY --from=source ${AMENT_WS}/src src + +# Dependency Cleanup +WORKDIR / +RUN apt-get -qq autoremove -y && apt-get -qq autoclean && apt-get -qq clean && \ + rm -rf /root/* /root/.ros /tmp/* /var/lib/apt/lists/* /usr/share/doc/* + +################################ Build ################################ +FROM dependencies as build + +# Build ROS2 packages +WORKDIR ${AMENT_WS} +RUN . /opt/ros/$ROS_DISTRO/setup.sh && \ + colcon build \ + --cmake-args -DCMAKE_BUILD_TYPE=Release + +# Entrypoint will run before any CMD on launch. Sources ~/opt//setup.bash and ~/ament_ws/install/setup.bash +COPY docker/wato_ros_entrypoint.sh ${AMENT_WS}/wato_ros_entrypoint.sh +ENTRYPOINT ["./wato_ros_entrypoint.sh"] + +################################ Prod ################################ +FROM build as deploy + +# Source Cleanup and Security Setup +RUN chown -R $USER:$USER ${AMENT_WS} +RUN rm -rf src/* + +USER ${USER} diff --git a/modules/dev_overrides/docker-compose.perception.yaml b/modules/dev_overrides/docker-compose.perception.yaml index 3a1a522d..4dcf2693 100644 --- a/modules/dev_overrides/docker-compose.perception.yaml +++ b/modules/dev_overrides/docker-compose.perception.yaml @@ -64,3 +64,13 @@ services: command: tail -F anything volumes: - ${MONO_DIR}/src/perception/tracking:/home/bolty/ament_ws/src/tracking + + depth_estimation: + <<: *fixuid + extends: + file: ../docker-compose.perception.yaml + service: tracking + image: "${PERCEPTION_DEPTH_ESTIMATION_IMAGE}:build_${TAG}" + command: tail -F anything + volumes: + - ${MONO_DIR}/src/perception/depth_estimation:/home/bolty/ament_ws/src/depth_estimation diff --git a/modules/docker-compose.perception.yaml b/modules/docker-compose.perception.yaml index 75d9d165..d30474f9 100644 --- a/modules/docker-compose.perception.yaml +++ b/modules/docker-compose.perception.yaml @@ -78,3 +78,14 @@ services: target: deploy image: "${PERCEPTION_TRACKING_IMAGE}:${TAG}" command: /bin/bash -c "ros2 launch tracking tracking.launch.py" + + depth_estimation: + build: + context: .. + dockerfile: docker/perception/depth_estimation/depth_estimation.Dockerfile + cache_from: + - "${PERCEPTION_DEPTH_ESTIMATION_IMAGE}:build_${TAG}" + - "${PERCEPTION_DEPTH_ESTIMATION_IMAGE}:build_main" + target: deploy + image: "${PERCEPTION_DEPTH_ESTIMATION_IMAGE}:${TAG}" + command: /bin/bash -c "ros2 launch depth_estimation eve.launch.py" diff --git a/src/perception/depth_estimation/CMakeLists.txt b/src/perception/depth_estimation/CMakeLists.txt new file mode 100644 index 00000000..fb6f76f5 --- /dev/null +++ b/src/perception/depth_estimation/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.5) +project(depth_estimation) + +# Default to C++14 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(sensor_msgs REQUIRED) + +include_directories(include) + +add_executable(depth_estimation_node src/depth_estimation_node.cpp) +ament_target_dependencies(depth_estimation_node rclcpp sensor_msgs) + +install(TARGETS + depth_estimation_node + DESTINATION lib/${PROJECT_NAME}) + +install(DIRECTORY + launch + DESTINATION share/${PROJECT_NAME} +) + +install(DIRECTORY + config + DESTINATION share/${PROJECT_NAME} +) + +ament_package() diff --git a/src/perception/depth_estimation/config/config.yaml b/src/perception/depth_estimation/config/config.yaml new file mode 100644 index 00000000..4f42e0b3 --- /dev/null +++ b/src/perception/depth_estimation/config/config.yaml @@ -0,0 +1,5 @@ +depth_estimation_node: + ros__parameters: + camera_topic: "/camera/left/image_color" + depth_map_topic: "/depth_map" + debug_node: false diff --git a/src/perception/depth_estimation/include/depth_estimation_node.hpp b/src/perception/depth_estimation/include/depth_estimation_node.hpp new file mode 100644 index 00000000..e54e9b6f --- /dev/null +++ b/src/perception/depth_estimation/include/depth_estimation_node.hpp @@ -0,0 +1,22 @@ +#ifndef DEPTH_ESTIMATION_NODE_HPP_ +#define DEPTH_ESTIMATION_NODE_HPP_ + +#include "rclcpp/rclcpp.hpp" +#include "sensor_msgs/msg/image.hpp" + +class DepthEstimationNode : public rclcpp::Node { + public: + DepthEstimationNode(); + + private: + void image_callback(const sensor_msgs::msg::Image::SharedPtr msg); + + std::string camera_topic_; + std::string depth_map_topic_; + bool debug_node_; + + rclcpp::Subscription::SharedPtr image_subscription_; + rclcpp::Publisher::SharedPtr depth_image_publisher_; +}; + +#endif // DEPTH_ESTIMATION_NODE_HPP_ diff --git a/src/perception/depth_estimation/launch/eve.launch.py b/src/perception/depth_estimation/launch/eve.launch.py new file mode 100644 index 00000000..8567b7e6 --- /dev/null +++ b/src/perception/depth_estimation/launch/eve.launch.py @@ -0,0 +1,25 @@ +from launch import LaunchDescription +from launch_ros.actions import Node +from ament_index_python.packages import get_package_share_directory +import os + + +def generate_launch_description(): + ld = LaunchDescription() + config = os.path.join( + get_package_share_directory('depth_estimation'), + 'config', + 'config.yaml' + ) + + depth_estimation_node = Node( + package='depth_estimation', + executable='depth_estimation_node', + name='depth_estimation_node', + parameters=[config], + arguments=['--ros-args', '--log-level', 'info'] + ) + + ld.add_action(depth_estimation_node) + + return ld diff --git a/src/perception/depth_estimation/package.xml b/src/perception/depth_estimation/package.xml new file mode 100644 index 00000000..76fc56c8 --- /dev/null +++ b/src/perception/depth_estimation/package.xml @@ -0,0 +1,16 @@ + + + + depth_estimation + 0.0.0 + Depth estimation ROS 2 node + TBD + TODO: License declaration + + ament_cmake + + + + ament_cmake + + diff --git a/src/perception/depth_estimation/src/depth_estimation_node.cpp b/src/perception/depth_estimation/src/depth_estimation_node.cpp new file mode 100644 index 00000000..bebd1ad0 --- /dev/null +++ b/src/perception/depth_estimation/src/depth_estimation_node.cpp @@ -0,0 +1,39 @@ +#include "depth_estimation_node.hpp" +#include "sensor_msgs/msg/image.hpp" + +DepthEstimationNode::DepthEstimationNode() : Node("depth_estimation_node") { + this->declare_parameter("camera_topic", "/camera/image_raw"); + this->declare_parameter("depth_map_topic", "/depth/image_raw"); + this->declare_parameter("deubg_node", false); + + this->get_parameter("camera_topic", camera_topic_); + this->get_parameter("depth_map_topic", depth_map_topic_); + this->get_parameter("debug_node", debug_node_); + + RCLCPP_INFO(this->get_logger(), "debug_node: %s", debug_node_ ? "true" : "false"); + + RCLCPP_INFO(this->get_logger(), "Subscribing to camera topic '%s'", camera_topic_.c_str()); + image_subscription_ = this->create_subscription( + camera_topic_, 10, + std::bind(&DepthEstimationNode::image_callback, this, std::placeholders::_1)); + + RCLCPP_INFO(this->get_logger(), "Publishing depth map to topic '%s'", depth_map_topic_.c_str()); + depth_image_publisher_ = this->create_publisher(depth_map_topic_, 10); +} + +void DepthEstimationNode::image_callback(const sensor_msgs::msg::Image::SharedPtr msg) { + RCLCPP_INFO(this->get_logger(), "Received sensor image on '%s'", camera_topic_.c_str()); + + // TODO: Process the incoming image and estimate depth + // Replace this empty image with the actual depth map + auto depth_map_image = sensor_msgs::msg::Image(); + depth_image_publisher_->publish(depth_map_image); +} + +int main(int argc, char **argv) { + rclcpp::init(argc, argv); + auto node = std::make_shared(); + rclcpp::spin(node); + rclcpp::shutdown(); + return 0; +} diff --git a/watod_scripts/watod-setup-env.sh b/watod_scripts/watod-setup-env.sh index 029e9233..a165c028 100755 --- a/watod_scripts/watod-setup-env.sh +++ b/watod_scripts/watod-setup-env.sh @@ -72,6 +72,7 @@ PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE=${PERCEPTION_CAMERA_OBJECT_DETECTION_IM PERCEPTION_LANE_DETECTION_IMAGE=${PERCEPTION_LANE_DETECTION_IMAGE:-"$REGISTRY_URL/perception/lane_detection"} PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE=${PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE:-"$REGISTRY_URL/perception/semantic_segmentation"} PERCEPTION_TRACKING_IMAGE=${PERCEPTION_TRACKING_IMAGE:-"$REGISTRY_URL/perception/tracking"} +PERCEPTION_DEPTH_ESTIMATION_IMAGE=${PERCEPTION_DEPTH_ESTIMATION_IMAGE:-"$REGISTRY_URL/perception/depth_estimation"} # World Modeling WORLD_MODELING_HD_MAP_IMAGE=${WORLD_MODELING_HD_MAP_IMAGE:-"$REGISTRY_URL/world_modeling/hd_map"} @@ -166,6 +167,7 @@ echo "PERCEPTION_CAMERA_OBJECT_DETECTION_IMAGE=$PERCEPTION_CAMERA_OBJECT_DETECTI echo "PERCEPTION_LANE_DETECTION_IMAGE=$PERCEPTION_LANE_DETECTION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE=$PERCEPTION_SEMANTIC_SEGMENTATION_IMAGE" >> "$MODULES_DIR/.env" echo "PERCEPTION_TRACKING_IMAGE=$PERCEPTION_TRACKING_IMAGE" >> "$MODULES_DIR/.env" +echo "PERCEPTION_DEPTH_ESTIMATION_IMAGE=$PERCEPTION_DEPTH_ESTIMATION_IMAGE" >> "$MODULES_DIR/.env" # World Modeling echo "WORLD_MODELING_HD_MAP_IMAGE=$WORLD_MODELING_HD_MAP_IMAGE" >> "$MODULES_DIR/.env" From f6293ed9dbdece79fa9d848497d56735ab581073 Mon Sep 17 00:00:00 2001 From: Justin Leung Date: Fri, 22 Mar 2024 06:27:25 +0000 Subject: [PATCH 15/15] Skip CI building perception modules with large image size --- .github/templates/docker_context/docker_context.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/templates/docker_context/docker_context.sh b/.github/templates/docker_context/docker_context.sh index 126b5cb2..e8dc0d1f 100755 --- a/.github/templates/docker_context/docker_context.sh +++ b/.github/templates/docker_context/docker_context.sh @@ -36,6 +36,12 @@ while read -r module; do # Loop through each service while read -r service_out; do + # Temporarily skip perception services that have too large image size + if [[ "$service_out" == "lane_detection" ]] || \ + [[ "$service_out" == "camera_object_detection" ]] || \ + [[ "$service_out" == "semantic_segmentation" ]]; then + continue + fi # Construct JSON object for each service with module and service name json_object=$(jq -nc --arg module_out "$module_out" --arg service_out "$service_out" \ '{module: $module_out, service: $service_out}')