diff --git a/realsense2_camera/CMakeLists.txt b/realsense2_camera/CMakeLists.txt index e998dd375d..a056cfbb18 100644 --- a/realsense2_camera/CMakeLists.txt +++ b/realsense2_camera/CMakeLists.txt @@ -303,36 +303,56 @@ if(BUILD_TESTING) test/rosbag test/post_processing_filters ) + + + + foreach(test_folder ${_pytest_folders}) + file(GLOB files "${test_folder}/test_*.py") + foreach(file ${files}) + + get_filename_component(_test_name ${file} NAME_WE) + ament_add_pytest_test(${_test_name} ${file} + APPEND_ENV PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_SOURCE_DIR}/test/utils:${CMAKE_SOURCE_DIR}/launch:${CMAKE_SOURCE_DIR}/scripts + TIMEOUT 60 + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + endforeach() + endforeach() + + unset(_pytest_folders) + set(rs_query_cmd "rs-enumerate-devices -s") execute_process(COMMAND bash -c ${rs_query_cmd} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} RESULT_VARIABLE rs_result OUTPUT_VARIABLE RS_DEVICE_INFO) - - # message(STATUS "rs_result ${rs_result}") message(STATUS "rs_device_info:") message(STATUS "${RS_DEVICE_INFO}") if(RS_DEVICE_INFO MATCHES "D455") message(STATUS "D455 device found") - set(_pytest_folders - ${_pytest_folders} - test/d455 + set(_pytest_live_folders + test/live_camera + ) + elseif(RS_DEVICE_INFO MATCHES "D415") + message(STATUS "D415 device found") + set(_pytest_live_folders + test/live_camera ) endif() - - foreach(test_folder ${_pytest_folders}) + foreach(test_folder ${_pytest_live_folders}) file(GLOB files "${test_folder}/test_*.py") foreach(file ${files}) get_filename_component(_test_name ${file} NAME_WE) ament_add_pytest_test(${_test_name} ${file} APPEND_ENV PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_SOURCE_DIR}/test/utils:${CMAKE_SOURCE_DIR}/launch:${CMAKE_SOURCE_DIR}/scripts - TIMEOUT 60 + TIMEOUT 500 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) endforeach() endforeach() + endif() # Ament exports diff --git a/realsense2_camera/test/d455/test_d455_all_profile_tests.py b/realsense2_camera/test/d455/test_d455_all_profile_tests.py deleted file mode 100644 index 6ce8b8789f..0000000000 --- a/realsense2_camera/test/d455/test_d455_all_profile_tests.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2023 Intel Corporation. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import os -import sys -import itertools - - -import pytest -import rclpy - -from sensor_msgs.msg import Image as msg_Image -from sensor_msgs.msg import Imu as msg_Imu -from sensor_msgs.msg import PointCloud2 as msg_PointCloud2 - -import numpy as np - -sys.path.append(os.path.abspath(os.path.dirname(__file__)+"/../utils")) -import pytest_rs_utils -from pytest_rs_utils import launch_descr_with_parameters -from pytest_rs_utils import delayed_launch_descr_with_parameters -from pytest_rs_utils import get_rosbag_file_path -import pytest_live_camera_utils -from rclpy.parameter import Parameter -from rcl_interfaces.msg import ParameterValue -from rcl_interfaces.srv import SetParameters, GetParameters, ListParameters - -test_params_all_profiles = { - 'camera_name': 'D455', - 'device_type': 'D455', - } -''' -This test was implemented as a template to set the parameters and run the test. -This directory is not added to the CMakeLists.txt so as to avoid the colcon failure in the -machines that don't have the D455 connected. -1. Only a subset of parameter types are implemented in py_rs_utils, it has to be extended for others -2. After setting the param, rclpy.spin_once may be needed.Test passes even without this though. -''' -@pytest.mark.parametrize("launch_descr_with_parameters", [test_params_all_profiles],indirect=True) -@pytest.mark.launch(fixture=launch_descr_with_parameters) -class TestD455_Change_Resolution(pytest_rs_utils.RsTestBaseClass): - def test_D455_Change_Resolution(self,launch_descr_with_parameters): - params = launch_descr_with_parameters[1] - themes = [ - {'topic':'/'+params['camera_name']+'/color/image_raw', - 'msg_type':msg_Image, - 'expected_data_chunks':1, - #'data':data - } - ] - try: - ''' - initialize, run and check the data - ''' - serial_no = None - if 'serial_no' in params: - serial_no = params['serial_no'] - cap = pytest_live_camera_utils.get_camera_capabilities(params['device_type'], serial_no) - self.init_test("RsTest"+params['camera_name']) - self.create_param_ifs(params['camera_name'] + '/' + params['camera_name']) - for profile in cap["color_profile"]: - if profile[0] == 'Color': - print("Testing :" + profile[1] + " " + profile[2]) - if "BGRA8" == profile[2]: - print("Skipping BGRA8" ) - continue - if "RGBA8" == profile[2]: - print("Skipping RGBA8" ) - continue - if "Y8" == profile[2]: - print("Skipping Y8" ) - continue - self.set_string_param('rgb_camera.profile', profile[1]) - self.set_string_param('rgb_camera.color_format', profile[2]) - self.set_bool_param('enable_color', True) - themes[0]['width'] = int(profile[1].split('x')[0]) - themes[0]['height'] = int(profile[1].split('x')[1]) - ret = self.run_test(themes) - assert ret[0], ret[1] - assert self.process_data(themes) - - ret = self.run_test(themes) - assert self.process_data(themes) - finally: - #this step is important because the test will fail next time - pytest_rs_utils.kill_realsense2_camera_node() - self.shutdown() - - diff --git a/realsense2_camera/test/live_camera/test_camera_all_profile_tests.py b/realsense2_camera/test/live_camera/test_camera_all_profile_tests.py new file mode 100644 index 0000000000..1fdec0c75d --- /dev/null +++ b/realsense2_camera/test/live_camera/test_camera_all_profile_tests.py @@ -0,0 +1,284 @@ +# Copyright 2023 Intel Corporation. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import os +import sys +import itertools + + +import pytest +import rclpy + +from sensor_msgs.msg import Image as msg_Image +from sensor_msgs.msg import Imu as msg_Imu +from sensor_msgs.msg import PointCloud2 as msg_PointCloud2 + +import numpy as np + +sys.path.append(os.path.abspath(os.path.dirname(__file__)+"/../utils")) +import pytest_rs_utils +from pytest_rs_utils import launch_descr_with_parameters +from pytest_rs_utils import delayed_launch_descr_with_parameters +from pytest_rs_utils import get_rosbag_file_path +import pytest_live_camera_utils +from rclpy.parameter import Parameter +from rcl_interfaces.msg import ParameterValue +from rcl_interfaces.srv import SetParameters, GetParameters, ListParameters + +test_params_all_profiles_d455 = { + 'camera_name': 'D455', + 'device_type': 'D455', + } +test_params_all_profiles_d415 = { + 'camera_name': 'D415', + 'device_type': 'D415', + } +''' +This test was implemented as a template to set the parameters and run the test. +This directory is not added to the CMakeLists.txt so as to avoid the colcon failure in the +machines that don't have the D455 connected. +1. Only a subset of parameter types are implemented in py_rs_utils, it has to be extended for others +2. After setting the param, rclpy.spin_once may be needed.Test passes even without this though. +''' +@pytest.mark.parametrize("launch_descr_with_parameters", [test_params_all_profiles_d415,test_params_all_profiles_d455],indirect=True) +@pytest.mark.launch(fixture=launch_descr_with_parameters) +class TestLiveCamera_Change_Resolution(pytest_rs_utils.RsTestBaseClass): + def test_LiveCamera_Change_Resolution(self,launch_descr_with_parameters): + skipped_tests = [] + params = launch_descr_with_parameters[1] + themes = [ + {'topic':'/'+params['camera_name']+'/color/image_raw', + 'msg_type':msg_Image, + 'expected_data_chunks':1, + #'data':data + } + ] + depth_themes = [ + {'topic':'/'+params['camera_name']+'/depth/image_rect_raw', + 'msg_type':msg_Image, + 'expected_data_chunks':1, + #'data':data + } + ] + infra_themes = [ + {'topic':'/'+params['camera_name']+'/infra/image_rect_raw', + 'msg_type':msg_Image, + 'expected_data_chunks':1, + #'data':data + } + ] + infra1_themes = [ + {'topic':'/'+params['camera_name']+'/infra1/image_rect_raw', + 'msg_type':msg_Image, + 'expected_data_chunks':1, + #'data':data + } + ] + infra2_themes = [ + {'topic':'/'+params['camera_name']+'/infra2/image_rect_raw', + 'msg_type':msg_Image, + 'expected_data_chunks':1, + #'data':data + } + ] + try: + ''' + initialize, run and check the data + ''' + serial_no = None + if 'serial_no' in params: + serial_no = params['serial_no'] + cap = pytest_live_camera_utils.get_camera_capabilities(params['device_type'], serial_no) + self.init_test("RsTest"+params['camera_name']) + self.create_param_ifs(params['camera_name'] + '/' + params['camera_name']) + for profile in cap["color_profile"]: + if profile[0] == 'Color': + print("Testing :"+ profile[0] + " " + profile[1] + " " + profile[2]) + if "BGRA8" == profile[2]: + print("Skipping " +profile[2]) + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + continue + if "RGBA8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "Y8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + self.set_bool_param('enable_color', False) + self.set_bool_param('enable_depth', False) + self.set_bool_param('enable_infra', False) + self.set_bool_param('enable_infra1', False) + self.set_bool_param('enable_infra2', False) + self.set_string_param('rgb_camera.profile', profile[1]) + self.set_string_param('rgb_camera.color_format', profile[2]) + self.set_bool_param('enable_color', True) + themes[0]['width'] = int(profile[1].split('x')[0]) + themes[0]['height'] = int(profile[1].split('x')[1]) + ret = self.run_test(themes) + assert ret[0], ret[1] + assert self.process_data(themes) + for profile in cap["depth_profile"]: + self.set_bool_param('enable_color', False) + self.set_bool_param('enable_depth', False) + self.set_bool_param('enable_infra', False) + self.set_bool_param('enable_infra1', False) + self.set_bool_param('enable_infra2', False) + if profile[0] == 'Depth': + print("Testing :"+ profile[0] + " " + profile[1] + " " + profile[2]) + if "Z16" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + self.set_string_param('depth_module.profile', profile[1]) + self.set_string_param('depth_module.depth_format', profile[2]) + self.set_bool_param('enable_depth', True) + depth_themes[0]['width'] = int(profile[1].split('x')[0]) + depth_themes[0]['height'] = int(profile[1].split('x')[1]) + ret = self.run_test(depth_themes) + assert ret[0], ret[1] + assert self.process_data(depth_themes) + + + if profile[0] == 'Infrared': + print("Testing :"+ profile[0] + " " + profile[1] + " " + profile[2]) + if "Y8" == profile[2]: + skipped_tests.append( profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "Y16" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "BGRA8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "RGBA8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "Y10BPACK" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "UYVY" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "BGR8" == profile[2]: + print("Skipping " +profile[2]) + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + continue + if "RGB8" == profile[2]: + print("Skipping " +profile[2]) + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + continue + if "RAW10" == profile[2]: + print("Skipping " +profile[2]) + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + continue + self.set_string_param('depth_module.profile', profile[1]) + self.set_string_param('depth_module.infra_format', profile[2]) + self.set_bool_param('enable_infra', True) + infra_themes[0]['width'] = int(profile[1].split('x')[0]) + infra_themes[0]['height'] = int(profile[1].split('x')[1]) + ret = self.run_test(infra_themes) + assert ret[0], ret[1] + assert self.process_data(infra_themes) + if profile[0] == 'Infrared1': + print("Testing :"+ profile[0] + " " + profile[1] + " " + profile[2]) + if "Y8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "Y16" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "Y10BPACK" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "UYVY" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "BGR8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "RGB8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "RAW10" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + self.set_string_param('depth_module.profile', profile[1]) + self.set_string_param('depth_module.infra1_format', profile[2]) + self.set_bool_param('enable_infra1', True) + infra1_themes[0]['width'] = int(profile[1].split('x')[0]) + infra1_themes[0]['height'] = int(profile[1].split('x')[1]) + ret = self.run_test(infra1_themes) + assert ret[0], ret[1] + assert self.process_data(infra1_themes) + if profile[0] == 'Infrared2': + if "Y8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "Y16" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "Y10BPACK" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "UYVY" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "BGR8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "RGB8" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + if "RAW10" == profile[2]: + skipped_tests.append(profile[0] + " " + profile[1] + " " + profile[2]) + print("Skipping " +profile[2]) + continue + self.set_string_param('depth_module.profile', profile[1]) + self.set_string_param('depth_module.infra2_format', profile[2]) + self.set_bool_param('enable_infra2', True) + infra2_themes[0]['width'] = int(profile[1].split('x')[0]) + infra2_themes[0]['height'] = int(profile[1].split('x')[1]) + ret = self.run_test(infra2_themes) + assert ret[0], ret[1] + assert self.process_data(infra2_themes) + finally: + #this step is important because the test will fail next time + pytest_rs_utils.kill_realsense2_camera_node() + self.shutdown() + print("\nSkipped tests:" + params['device_type']) + print("\n".join(skipped_tests)) + + diff --git a/realsense2_camera/test/d455/test_d455_basic_tests.py b/realsense2_camera/test/live_camera/test_d455_basic_tests.py similarity index 100% rename from realsense2_camera/test/d455/test_d455_basic_tests.py rename to realsense2_camera/test/live_camera/test_d455_basic_tests.py diff --git a/realsense2_camera/test/utils/pytest_rs_utils.py b/realsense2_camera/test/utils/pytest_rs_utils.py index 20e9fded71..b58d93307b 100644 --- a/realsense2_camera/test/utils/pytest_rs_utils.py +++ b/realsense2_camera/test/utils/pytest_rs_utils.py @@ -92,12 +92,13 @@ def init(self): def get_rosbag_path(self, filename): if filename in self.rosbag_files: return self.rosbag_location + "/" + filename -rosbagMgr = RosbagManager() + def get_rosbag_file_path(filename): + rosbagMgr = RosbagManager() path = rosbagMgr.get_rosbag_path(filename) assert path, "No rosbag file found :"+filename return path - +get_rosbag_file_path.rosbagMgr = None def CameraInfoGetData(rec_filename, topic): data = importRosbag(rec_filename, importTopics=[topic], log='ERROR', disable_bar=True)[topic]