Skip to content

Commit

Permalink
Merge pull request #354 from ros-drivers/291-add-renode-test
Browse files Browse the repository at this point in the history
291 update integration test, prepare CI to run renode
  • Loading branch information
flynneva authored Jan 26, 2025
2 parents ca78cd2 + 6b126bd commit 7b3dc6d
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 465 deletions.
74 changes: 41 additions & 33 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ name: Build and Test
on:
push:
branches:
- 'ros2'
- 'main'
pull_request:
branches:
- 'ros2/*'
- 'ros2'
- 'main/*'
- 'main'
workflow_dispatch:

env:
ROS_WORKSPACE_PATH: workspace/src

jobs:
get_ros_distros:
runs-on: ubuntu-latest
Expand All @@ -26,7 +29,7 @@ jobs:
- name: Generate actions matrix
id: set-matrix
run: |
ACTIVE_ROS_DISTROS=(noetic)
ACTIVE_ROS_DISTROS=()
DOCKER_DISTRO_MATRIX=()
RAW_DOCKER_JSON=$(curl -s "https://hub.docker.com/v2/repositories/rostooling/setup-ros-docker/tags?page_size=1000")
while read distro; do
Expand Down Expand Up @@ -73,44 +76,49 @@ jobs:
container:
image: rostooling/setup-ros-docker:${{ matrix.docker_image }}
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install policykit-1 libgtk2.0-common screen uml-utilities libc6-dev libicu-dev gcc python3 python3-pip
mkdir renode_portable
wget https://builds.renode.io/renode-latest.linux-portable.tar.gz
tar xf renode-latest.linux-portable.tar.gz -C renode_portable --strip-components=1
- name: Setup Directories
run: mkdir -p ros_ws/src
run: mkdir -p $ROS_WORKSPACE_PATH
- name: checkout
uses: actions/checkout@v4
with:
path: ros_ws/src
- name: Build and Test ROS 1
uses: ros-tooling/action-ros-ci@master
if: ${{ contains('["melodic", "noetic"]', matrix.ros_distro) }}
continue-on-error: true
with:
package-name: usb_cam
target-ros1-distro: ${{ matrix.ros_distro }}
vcs-repo-file-url: ""
- name: Build and Test ROS 2
id: build_and_test_step
uses: ros-tooling/action-ros-ci@master
if: ${{ contains('["melodic", "noetic"]', matrix.ros_distro) == false }}
with:
package-name: usb_cam
target-ros2-distro: ${{ matrix.ros_distro }}
vcs-repo-file-url: ""
colcon-defaults: |
{
"build": {
"mixin": ["coverage-gcc"]
}
}
# If possible, pin the repository in the workflow to a specific commit to avoid
# changes in colcon-mixin-repository from breaking your tests.
colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/1ddb69bedfd1f04c2f000e95452f7c24a4d6176b/index.yaml
- uses: actions/upload-artifact@v1
path: $ROS_WORKSPACE_PATH/usb_cam
- name: build
shell: bash
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
cd $ROS_WORKSPACE_PATH
colcon build --packages-select usb_cam
- name: unit tests
shell: bash
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
cd $ROS_WORKSPACE_PATH
colcon test --packages-select usb_cam
# Compile again, this time enabling integration tests
- name: Build integration tests
shell: bash
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
cd $ROS_WORKSPACE_PATH
colcon build --packages-select usb_cam --cmake-args -DSANITIZE=1 -DINTEGRATION_TESTS=1
- name: Run integration tests
shell: bash
run: |
renode_portable/renode --disable-gui --version
- uses: actions/upload-artifact@v4
with:
name: colcon-logs-${{ matrix.ros_distro }}
path: ${{ steps.build_and_test_step.outputs.ros-workspace-directory-name }}/log
if: always()
continue-on-error: true
- uses: actions/upload-artifact@v1
- uses: actions/upload-artifact@v4
with:
name: lcov-logs-${{ matrix.ros_distro }}
path: ${{ steps.build_and_test_step.outputs.ros-workspace-directory-name }}/lcov
Expand Down
164 changes: 56 additions & 108 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,11 @@ if(NOT CMAKE_CXX_STANDARD)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if($ENV{ROS_VERSION} EQUAL 2)
add_compile_options(-Wall -Wextra -Wpedantic -Werror)
endif()
add_compile_options(-Wall -Wextra -Wpedantic -Werror)
endif()

# Remove once ROS 1 Noetic is deprecated
if($ENV{ROS_VERSION} EQUAL 1)
find_package(catkin REQUIRED COMPONENTS
cv_bridge
roscpp
std_msgs
std_srvs
sensor_msgs
camera_info_manager
image_transport)
else()
find_package(ament_cmake_auto REQUIRED)
ament_auto_find_build_dependencies()
endif()
find_package(ament_cmake_auto REQUIRED)
ament_auto_find_build_dependencies()

find_package(OpenCV REQUIRED)

Expand Down Expand Up @@ -63,103 +49,65 @@ target_link_libraries(${PROJECT_NAME}
${swscale_LIBRARIES}
${OpenCV_LIBRARIES})

# Remove once ROS 1 Noetic is deprecated
if($ENV{ROS_VERSION} EQUAL 1)
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
)

add_executable(${PROJECT_NAME}_node src/ros1/usb_cam_node.cpp)
target_link_libraries(${PROJECT_NAME}_node
${PROJECT_NAME}
${catkin_LIBRARIES}
)
target_include_directories(${PROJECT_NAME}_node PUBLIC
${catkin_INCLUDE_DIRS})
else()
ament_export_libraries(${PROJECT_NAME})

## Declare a ROS 2 composible node as a library
ament_auto_add_library(${PROJECT_NAME}_node SHARED
src/ros2/usb_cam_node.cpp
)

target_link_libraries(${PROJECT_NAME}_node
${PROJECT_NAME})
ament_export_libraries(${PROJECT_NAME})

## Use node to generate an executable
rclcpp_components_register_node(${PROJECT_NAME}_node
PLUGIN "usb_cam::UsbCamNode"
EXECUTABLE ${PROJECT_NAME}_node_exe
)
if(SANITIZE)
target_compile_options(${PROJECT_NAME} PUBLIC -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME} -fsanitize=address -fsanitize=leak)
target_compile_options(${PROJECT_NAME}_node PUBLIC -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME}_node -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME}_node_exe -fsanitize=address -fsanitize=leak)
endif()
endif()
## Declare a ROS 2 composible node as a library
ament_auto_add_library(${PROJECT_NAME}_node SHARED
src/usb_cam_node.cpp
)

if(BUILD_TESTING)
if($ENV{ROS_VERSION} EQUAL 2)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
target_link_libraries(${PROJECT_NAME}_node
${PROJECT_NAME})

find_package(ament_cmake_gtest)
## Use node to generate an executable
rclcpp_components_register_node(${PROJECT_NAME}_node
PLUGIN "usb_cam::UsbCamNode"
EXECUTABLE ${PROJECT_NAME}_node_exe
)

# Unit tests
ament_add_gtest(test_usb_cam_utils
test/test_usb_cam_utils.cpp)
target_link_libraries(test_usb_cam_utils
${PROJECT_NAME})
ament_add_gtest(test_pixel_formats
test/test_pixel_formats.cpp)
target_link_libraries(test_pixel_formats
if(SANITIZE)
target_compile_options(${PROJECT_NAME} PUBLIC -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME} -fsanitize=address -fsanitize=leak)
target_compile_options(${PROJECT_NAME}_node PUBLIC -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME}_node -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME}_node_exe -fsanitize=address -fsanitize=leak)
endif()

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
find_package(ament_cmake_gtest)
# Unit tests
ament_add_gtest(test_usb_cam_utils
test/test_usb_cam_utils.cpp)
target_link_libraries(test_usb_cam_utils
${PROJECT_NAME})
ament_add_gtest(test_pixel_formats
test/test_pixel_formats.cpp)
target_link_libraries(test_pixel_formats
${PROJECT_NAME})
if(INTEGRATION_TESTS)
ament_add_gtest(test_usb_cam_lib
test/test_usb_cam_lib.cpp)
target_link_libraries(test_usb_cam_lib
${PROJECT_NAME})
# TODO(flynneva): rewrite this test in another PR
# Integration tests
# ament_add_gtest(test_usb_cam_lib
# test/test_usb_cam_lib.cpp)
# target_link_libraries(test_usb_cam_lib
# ${PROJECT_NAME})
endif()
endif()

install(
PROGRAMS scripts/show_image.py
DESTINATION lib/${PROJECT_NAME})

if($ENV{ROS_VERSION} EQUAL 1)
install(TARGETS ${PROJECT_NAME}_node ${PROJECT_NAME}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
)

## Copy launch files
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
FILES_MATCHING PATTERN "*.launch"
)

install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
)
else()
install(
PROGRAMS scripts/show_image.py
DESTINATION lib/${PROJECT_NAME})

install(TARGETS
${PROJECT_NAME}
${PROJECT_NAME}_node
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION lib
)

ament_auto_package(
INSTALL_TO_SHARE
launch
config
)
endif()
install(TARGETS
${PROJECT_NAME}
${PROJECT_NAME}_node
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION lib
)

ament_auto_package(
INSTALL_TO_SHARE
launch
config
)
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,25 @@ Unfortunately `rviz2` and `show_image.py` do not support visualizing the compres
ros2 run image_transport republish compressed raw --ros-args --remap in/compressed:=image_raw/compressed --remap out:=image_raw/uncompressed
```

## Address and leak sanitizing
## Testing

To run the basic unit tests for this repository:

```shell
colcon build --packages-select usb_cam
colcon test --pacakges-select usb_cam
```

### Integration tests

To run integration tests for this repository:

```shell
colcon build --packages-select usb_cam --cmake-args -DINTEGRATION_TESTS=1
colcon test --pacakges-select usb_cam
```

### Address and leak sanitizing

Incorporated into the `CMakelists.txt` file to assist with memory leak and address sanitizing
is a flag to add these compile commands to the targets.
Expand Down
47 changes: 21 additions & 26 deletions include/usb_cam/usb_cam.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,32 +104,27 @@ typedef struct

typedef struct
{
std::string camera_name; // can be anything
std::string device_name; // usually /dev/video0 or something similiar
std::string frame_id;
std::string io_method_name;
std::string camera_info_url;
// these parameters all have to be a combination supported by the device
// Use
// v4l2-ctl --device=0 --list-formats-ext
// to discover them,
// or guvcview
std::string pixel_format_name;
std::string av_device_format;
int image_width;
int image_height;
int framerate;
int brightness;
int contrast;
int saturation;
int sharpness;
int gain;
int white_balance;
int exposure;
int focus;
bool auto_white_balance;
bool autoexposure;
bool autofocus;
std::string camera_name = "usb_cam"; // can be anything
std::string device_name = "/dev/video0"; // usually /dev/video0 or something similiar
std::string frame_id = "camera";
std::string io_method_name = "mmap";
std::string camera_info_url = "package://usb_cam/config/camera_info.yaml";
std::string pixel_format_name = "yuyv2rgb";
std::string av_device_format = "YUV422P";
int image_width = 600;
int image_height = 400;
int framerate = 30.0;
int brightness = -1;
int contrast = -1;
int saturation = -1;
int sharpness = -1;
int gain = -1;
int white_balance = -1;
int exposure = -1;
int focus = -1;
bool auto_white_balance = true;
bool autoexposure = true;
bool autofocus = false;
} parameters_t;

typedef struct
Expand Down
Loading

0 comments on commit 7b3dc6d

Please sign in to comment.