From 0eab7eafde8f9f6efeb56e37a0948cbb2e38aed8 Mon Sep 17 00:00:00 2001 From: Julien Thierry Date: Wed, 11 Oct 2023 11:01:02 +0200 Subject: [PATCH] Release v4.4.0 --- CMakeLists.txt | 76 ++-- README.md | 44 +- cmake/custom_functions/add_android_app.cmake | 2 +- .../add_library_version_header.cmake | 4 +- .../custom_functions/common_macros.cmake | 6 +- cmake/custom_functions/lfs_download.cmake | 65 ++- .../custom_targets/README_metavision_open.md | 44 +- .../create_metavision_open_archive.cmake | 5 +- ...reate_metavision_open_archive_folder.cmake | 6 +- hal/cpp/CMakeLists.txt | 3 +- .../metavision/hal/decoders/mtr/mtr_decoder.h | 229 ++++++++++ .../metavision/hal/facilities/i_decoder.h | 3 +- .../hal/facilities/i_event_frame_decoder.h | 28 +- .../i_event_rate_activity_filter_module.h | 104 +++++ .../hal/facilities/i_events_stream_decoder.h | 2 +- .../include/metavision/hal/facilities/i_roi.h | 13 + .../hal/facilities/i_roi_pixel_mask.h | 50 +++ .../metavision/hal/utils/hal_error_code.h | 3 +- hal/cpp/samples/CMakeLists.txt | 3 +- .../samples/metavision_hal_ls/CMakeLists.txt | 4 +- .../metavision_hal_raw_cutter/CMakeLists.txt | 4 +- .../CMakeLists.txt | 4 +- .../test/CMakeLists.txt | 2 +- .../metavision_hal_seek/CMakeLists.txt | 4 +- .../metavision_hal_showcase/CMakeLists.txt | 4 +- .../metavision_hal_showcase.cpp | 12 +- .../metavision_hal_sync/CMakeLists.txt | 4 +- .../metavision_hal_sync.cpp | 2 +- .../metavision_platform_info/CMakeLists.txt | 4 +- .../CMakeLists.txt.install | 0 .../metavision_platform_info.cpp | 0 .../dummy_test_plugin_facilities_builder.cpp | 53 ++- hal/cpp/test/dummy_test_plugin_gtest.cpp | 4 +- hal/python/bindings/CMakeLists.txt | 21 +- ...ent_rate_activity_filter_module_python.cpp | 57 +++ ...python.cpp => i_roi_pixel_mask_python.cpp} | 21 +- hal_psee_plugins/CMakeLists.txt | 8 +- .../devices/genx320/genx320_cx3_tz_device.h | 12 +- .../include/devices/utils/device_system_id.h | 4 + hal_psee_plugins/lib/CMakeLists.txt | 7 + .../gen31_event_rate_noise_filter_module.h | 21 +- .../devices/gen31/gen31_roi_command.h | 2 + .../devices/gen41/gen41_roi_command.h | 4 +- .../devices/genx320/genx320_dem_driver.h | 68 +++ .../devices/genx320/genx320_dem_interface.h | 64 +++ .../devices/genx320/genx320_digital_crop.h | 59 +++ .../devices/genx320/genx320_ll_roi.h | 63 --- .../{genx320_nfl.h => genx320_nfl_driver.h} | 44 +- .../devices/genx320/genx320_nfl_interface.h | 38 +- .../devices/genx320/genx320_roi_driver.h | 160 +++++++ .../devices/genx320/genx320_roi_interface.h | 81 ++++ .../genx320_roi_pixel_mask_interface.h | 36 ++ .../psee_hw_layer/facilities/psee_roi.h | 15 +- ...avision_imx636_facility_casting_sample.cpp | 1 - hal_psee_plugins/src/devices/CMakeLists.txt | 30 +- .../gen31_event_rate_noise_filter_module.cpp | 22 + .../src/devices/gen31/gen31_roi_command.cpp | 6 + .../src/devices/gen41/gen41_roi_command.cpp | 19 +- .../src/devices/genx320/CMakeLists.txt | 14 +- .../devices/genx320/genx320_cx3_tz_device.cpp | 180 +++++++- .../devices/genx320/genx320_dem_driver.cpp | 206 +++++++++ .../devices/genx320/genx320_dem_interface.cpp | 55 +++ .../devices/genx320/genx320_digital_crop.cpp | 62 +++ .../src/devices/genx320/genx320_ll_roi.cpp | 241 ---------- .../src/devices/genx320/genx320_nfl.cpp | 87 ---- .../devices/genx320/genx320_nfl_driver.cpp | 184 ++++++++ .../devices/genx320/genx320_nfl_interface.cpp | 61 +++ .../devices/genx320/genx320_roi_driver.cpp | 420 ++++++++++++++++++ .../devices/genx320/genx320_roi_interface.cpp | 62 +++ .../genx320_roi_pixel_mask_interface.cpp | 57 +++ .../src/devices/imx636/imx636_tz_device.cpp | 2 +- .../src/devices/imx646/imx646_tz_device.cpp | 2 +- .../psee-video/tz_psee_video_build.cpp | 1 + .../src/devices/treuzell/tz_issd_device.cpp | 5 +- hal_psee_plugins/src/facilities/psee_roi.cpp | 24 +- hal_psee_plugins/src/utils/make_decoder.cpp | 31 +- .../src/utils/tz_device_control.cpp | 6 +- .../device_discovery_psee_plugins_gtest.cpp | 4 +- ...1_event_rate_noise_filter_module_gtest.cpp | 6 +- .../test/psee_raw_file_decoder_gtest.cpp | 77 ++++ sdk/modules/base/cpp/CMakeLists.txt | 4 +- .../sdk/base/events/event_pointcloud.h | 40 ++ .../base/cpp/{apps => samples}/CMakeLists.txt | 0 .../metavision_software_info/CMakeLists.txt | 4 +- .../CMakeLists.txt.install | 0 .../metavision_software_info.cpp | 0 .../test/CMakeLists.txt | 0 .../metavision_software_info_pytest.py.in | 0 sdk/modules/core/cpp/CMakeLists.txt | 3 +- sdk/modules/core/cpp/apps/CMakeLists.txt | 14 - sdk/modules/core/cpp/samples/CMakeLists.txt | 6 + .../metavision_composed_viewer/CMakeLists.txt | 4 +- .../metavision_csv_viewer/CMakeLists.txt | 4 +- .../CMakeLists.txt | 4 +- .../CMakeLists.txt | 4 +- .../metavision_event_frame_gpu_loading.cpp | 2 + .../metavision_file_to_video/CMakeLists.txt | 4 +- .../CMakeLists.txt.install | 0 .../metavision_file_to_video.cpp | 0 .../test/CMakeLists.txt | 0 .../test/metavision_file_to_video_pytest.py | 0 .../metavision_filtering/CMakeLists.txt | 4 +- .../metavision_player/CMakeLists.txt | 4 +- .../metavision_player/CMakeLists.txt.install | 0 .../metavision_player/inc/analysis_utils.h | 0 .../metavision_player/inc/analysis_view.h | 0 .../metavision_player/inc/camera_view.h | 0 .../metavision_player/inc/params.h | 0 .../metavision_player/inc/utils.h | 0 .../metavision_player/inc/view.h | 0 .../metavision_player/inc/viewer.h | 0 .../metavision_player/src/analysis_view.cpp | 0 .../metavision_player/src/camera_view.cpp | 0 .../metavision_player/src/main.cpp | 0 .../metavision_player/src/view.cpp | 0 .../metavision_player/src/viewer.cpp | 0 .../metavision_player/test/CMakeLists.txt | 0 .../metavision_player/test/player_gtest.cpp | 0 .../metavision_sdk_get_started/CMakeLists.txt | 4 +- .../metavision_time_surface/CMakeLists.txt | 4 +- .../metavision_time_surface.cpp | 4 +- sdk/modules/core/python/tests/CMakeLists.txt | 16 +- sdk/modules/core_ml/python/CMakeLists.txt | 3 +- .../core_ml/python/tests/CMakeLists.txt | 4 +- .../tests/demo_corner_detection_pytest.py | 4 +- .../MetavisionSDK_driverCPackConfig.cmake | 2 +- sdk/modules/driver/cpp/CMakeLists.txt | 1 - sdk/modules/driver/cpp/apps/CMakeLists.txt | 20 - .../metavision/sdk/driver/event_file_reader.h | 6 + sdk/modules/driver/cpp/samples/CMakeLists.txt | 17 +- .../CMakeLists.txt | 4 +- .../CMakeLists.txt.install | 0 .../metavision_active_pixel_detection.cpp | 26 +- .../metavision_file_cutter/CMakeLists.txt | 4 +- .../CMakeLists.txt.install | 0 .../metavision_file_cutter.cpp | 4 +- .../test/CMakeLists.txt | 0 .../test/metavision_file_cutter_pytest.py | 0 .../metavision_file_info/CMakeLists.txt | 4 +- .../CMakeLists.txt.install | 0 .../metavision_file_info.cpp | 0 .../metavision_file_info/test/CMakeLists.txt | 0 .../test/metavision_file_info_pytest.py | 0 .../metavision_file_to_csv/CMakeLists.txt | 4 +- .../metavision_file_to_dat/CMakeLists.txt | 4 +- .../CMakeLists.txt.install | 0 .../metavision_file_to_dat.cpp | 0 .../test/CMakeLists.txt | 0 .../test/metavision_file_to_dat_pytest.py | 0 .../metavision_file_to_hdf5/CMakeLists.txt | 4 +- .../CMakeLists.txt.install | 0 .../metavision_file_to_hdf5.cpp | 10 +- .../test/CMakeLists.txt | 0 .../test/metavision_file_to_hdf5_pytest.py | 0 .../metavision_viewer/CMakeLists.txt | 4 +- .../metavision_viewer/CMakeLists.txt.install | 0 .../metavision_viewer/metavision_viewer.cpp | 12 +- .../metavision_viewer_android/CMakeLists.txt | 1 - sdk/modules/driver/cpp/src/camera_live.cpp | 11 +- .../driver/cpp/src/camera_offline_raw.cpp | 8 + .../driver/cpp/src/camera_serialization.cpp | 55 +-- .../driver/cpp/src/event_file_reader.cpp | 20 + .../driver/internal/camera_live_internal.h | 2 + .../internal/event_file_reader_internal.h | 3 + .../protobuf/region_of_interest_state.proto | 6 - .../driver/cpp/src/raw_event_file_reader.cpp | 9 +- sdk/modules/driver/cpp/src/roi.cpp | 1 + sdk/modules/driver/cpp/tests/CMakeLists.txt | 2 +- sdk/modules/driver/cpp/tests/camera_gtest.cpp | 110 ++--- .../metavision_simple_window/CMakeLists.txt | 4 +- standalone_samples/CMakeLists.txt | 2 +- utils/CMakeLists.txt | 10 +- 172 files changed, 3020 insertions(+), 931 deletions(-) rename hal/cpp/apps/CMakeLists.txt => cmake/custom_functions/common_macros.cmake (76%) create mode 100644 hal/cpp/include/metavision/hal/decoders/mtr/mtr_decoder.h create mode 100644 hal/cpp/include/metavision/hal/facilities/i_event_rate_activity_filter_module.h create mode 100644 hal/cpp/include/metavision/hal/facilities/i_roi_pixel_mask.h rename hal/cpp/{apps => samples}/metavision_platform_info/CMakeLists.txt (87%) rename hal/cpp/{apps => samples}/metavision_platform_info/CMakeLists.txt.install (100%) rename hal/cpp/{apps => samples}/metavision_platform_info/metavision_platform_info.cpp (100%) create mode 100644 hal/python/bindings/i_event_rate_activity_filter_module_python.cpp rename hal/python/bindings/{i_event_rate_noise_filter_module_python.cpp => i_roi_pixel_mask_python.cpp} (55%) create mode 100644 hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_dem_driver.h create mode 100644 hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_dem_interface.h create mode 100644 hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_digital_crop.h delete mode 100644 hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_ll_roi.h rename hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/{genx320_nfl.h => genx320_nfl_driver.h} (54%) rename hal/cpp/include/metavision/hal/facilities/i_event_rate_noise_filter_module.h => hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h (63%) create mode 100644 hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_driver.h create mode 100644 hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_interface.h create mode 100644 hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_pixel_mask_interface.h create mode 100644 hal_psee_plugins/src/devices/genx320/genx320_dem_driver.cpp create mode 100644 hal_psee_plugins/src/devices/genx320/genx320_dem_interface.cpp create mode 100644 hal_psee_plugins/src/devices/genx320/genx320_digital_crop.cpp delete mode 100644 hal_psee_plugins/src/devices/genx320/genx320_ll_roi.cpp delete mode 100644 hal_psee_plugins/src/devices/genx320/genx320_nfl.cpp create mode 100644 hal_psee_plugins/src/devices/genx320/genx320_nfl_driver.cpp create mode 100644 hal_psee_plugins/src/devices/genx320/genx320_nfl_interface.cpp create mode 100644 hal_psee_plugins/src/devices/genx320/genx320_roi_driver.cpp create mode 100644 hal_psee_plugins/src/devices/genx320/genx320_roi_interface.cpp create mode 100644 hal_psee_plugins/src/devices/genx320/genx320_roi_pixel_mask_interface.cpp create mode 100644 sdk/modules/base/cpp/include/metavision/sdk/base/events/event_pointcloud.h rename sdk/modules/base/cpp/{apps => samples}/CMakeLists.txt (100%) rename sdk/modules/base/cpp/{apps => samples}/metavision_software_info/CMakeLists.txt (87%) rename sdk/modules/base/cpp/{apps => samples}/metavision_software_info/CMakeLists.txt.install (100%) rename sdk/modules/base/cpp/{apps => samples}/metavision_software_info/metavision_software_info.cpp (100%) rename sdk/modules/base/cpp/{apps => samples}/metavision_software_info/test/CMakeLists.txt (100%) rename sdk/modules/base/cpp/{apps => samples}/metavision_software_info/test/metavision_software_info_pytest.py.in (100%) delete mode 100644 sdk/modules/core/cpp/apps/CMakeLists.txt rename sdk/modules/core/cpp/{apps => samples}/metavision_file_to_video/CMakeLists.txt (88%) rename sdk/modules/core/cpp/{apps => samples}/metavision_file_to_video/CMakeLists.txt.install (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_file_to_video/metavision_file_to_video.cpp (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_file_to_video/test/CMakeLists.txt (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_file_to_video/test/metavision_file_to_video_pytest.py (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/CMakeLists.txt (89%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/CMakeLists.txt.install (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/inc/analysis_utils.h (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/inc/analysis_view.h (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/inc/camera_view.h (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/inc/params.h (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/inc/utils.h (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/inc/view.h (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/inc/viewer.h (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/src/analysis_view.cpp (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/src/camera_view.cpp (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/src/main.cpp (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/src/view.cpp (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/src/viewer.cpp (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/test/CMakeLists.txt (100%) rename sdk/modules/core/cpp/{apps => samples}/metavision_player/test/player_gtest.cpp (100%) delete mode 100644 sdk/modules/driver/cpp/apps/CMakeLists.txt rename sdk/modules/driver/cpp/{apps => samples}/metavision_active_pixel_detection/CMakeLists.txt (90%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_active_pixel_detection/CMakeLists.txt.install (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp (97%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_cutter/CMakeLists.txt (87%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_cutter/CMakeLists.txt.install (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_cutter/metavision_file_cutter.cpp (97%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_cutter/test/CMakeLists.txt (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_cutter/test/metavision_file_cutter_pytest.py (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_info/CMakeLists.txt (87%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_info/CMakeLists.txt.install (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_info/metavision_file_info.cpp (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_info/test/CMakeLists.txt (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_info/test/metavision_file_info_pytest.py (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_dat/CMakeLists.txt (87%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_dat/CMakeLists.txt.install (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_dat/metavision_file_to_dat.cpp (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_dat/test/CMakeLists.txt (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_dat/test/metavision_file_to_dat_pytest.py (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_hdf5/CMakeLists.txt (89%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_hdf5/CMakeLists.txt.install (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp (93%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_hdf5/test/CMakeLists.txt (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_file_to_hdf5/test/metavision_file_to_hdf5_pytest.py (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_viewer/CMakeLists.txt (88%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_viewer/CMakeLists.txt.install (100%) rename sdk/modules/driver/cpp/{apps => samples}/metavision_viewer/metavision_viewer.cpp (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index c67c42f26..5aed59ffe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ endif(NOT CMAKE_BUILD_TYPE) cmake_minimum_required(VERSION 3.5) -project(metavision VERSION 4.3.0) +project(metavision VERSION 4.4.0) set(PROJECT_VERSION_SUFFIX "") if(PROJECT_VERSION_SUFFIX STREQUAL "") @@ -71,12 +71,14 @@ include(CMakeDependentOption) include(overridden_cmake_functions) include(lfs_download) include(add_pytest) +include(common_macros) + if (ANDROID) # Setup 3rd party prebuilt libraries dir set(ANDROID_PREBUILT_3RDPARTY_ARCHIVE utils/android/prebuilt-3rdparty.tar.gz) set(ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR ${GENERATE_FILES_DIRECTORY}/android/3rdparty) if (NOT EXISTS ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}) - lfs_download(${ANDROID_PREBUILT_3RDPARTY_ARCHIVE}) + lfs_download(${ANDROID_PREBUILT_3RDPARTY_ARCHIVE} COMPILATION) message(STATUS "Unpacking ${ANDROID_PREBUILT_3RDPARTY_ARCHIVE} in ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}") file(MAKE_DIRECTORY ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}) execute_process( @@ -154,9 +156,7 @@ if (WIN32) endif() -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/utils/platforms/CMakeLists.txt") - add_subdirectory(utils/platforms) # Load platform specific cmake early to override necessary options -endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/utils/platforms/CMakeLists.txt") +add_subdirectory_if_exists(utils/platforms) # Load platform specific cmake early to override necessary options ################################################### CMake options @@ -242,30 +242,32 @@ if (BUILD_TESTING) set(PYTEST_CMD pytest) # TODO we need a proper way to find python executable path on the TARGET. endif(CMAKE_CROSSCOMPILING) - lfs_download(datasets/openeb/gen31_timer.raw) - lfs_download(datasets/openeb/gen31_timer.hdf5) - lfs_download(datasets/openeb/gen31_timer_holes.raw) - lfs_download(datasets/openeb/gen31_timer_holes.hdf5) - lfs_download(datasets/openeb/gen4_evt2_hand.raw) - lfs_download(datasets/openeb/gen4_evt2_hand.hdf5) - lfs_download(datasets/openeb/gen4_evt3_hand.raw) - lfs_download(datasets/openeb/gen4_evt3_hand.hdf5) - lfs_download(datasets/openeb/blinking_gen4_with_ext_triggers.raw) - lfs_download(datasets/openeb/blinking_gen4_with_ext_triggers.hdf5) - lfs_download(datasets/openeb/claque_doigt_evt21.raw) - lfs_download(datasets/openeb/claque_doigt_evt21.hdf5) - lfs_download(datasets/openeb/standup_evt21-legacy.raw) - lfs_download(datasets/openeb/standup_evt21-legacy.hdf5) - lfs_download(datasets/openeb/diff3d.raw) - lfs_download(datasets/openeb/histo3d.raw) - lfs_download(datasets/openeb/histo3d_padding.raw) - lfs_download(datasets/openeb/test_start_after_0.dat) - lfs_download(datasets/openeb/aer_8bits.raw) - lfs_download(datasets/openeb/aer_4bits.raw) + lfs_download(datasets/openeb/gen31_timer.raw VALIDATION) + lfs_download(datasets/openeb/gen31_timer.hdf5 VALIDATION) + lfs_download(datasets/openeb/gen31_timer_holes.raw VALIDATION) + lfs_download(datasets/openeb/gen31_timer_holes.hdf5 VALIDATION) + lfs_download(datasets/openeb/gen4_evt2_hand.raw VALIDATION) + lfs_download(datasets/openeb/gen4_evt2_hand.hdf5 VALIDATION) + lfs_download(datasets/openeb/gen4_evt3_hand.raw VALIDATION) + lfs_download(datasets/openeb/gen4_evt3_hand.hdf5 VALIDATION) + lfs_download(datasets/openeb/blinking_gen4_with_ext_triggers.raw VALIDATION) + lfs_download(datasets/openeb/blinking_gen4_with_ext_triggers.hdf5 VALIDATION) + lfs_download(datasets/openeb/claque_doigt_evt21.raw VALIDATION) + lfs_download(datasets/openeb/claque_doigt_evt21.hdf5 VALIDATION) + lfs_download(datasets/openeb/standup_evt21-legacy.raw VALIDATION) + lfs_download(datasets/openeb/standup_evt21-legacy.hdf5 VALIDATION) + lfs_download(datasets/openeb/diff3d.raw VALIDATION) + lfs_download(datasets/openeb/histo3d.raw VALIDATION) + lfs_download(datasets/openeb/histo3d_padding.raw VALIDATION) + lfs_download(datasets/openeb/test_start_after_0.dat VALIDATION) + lfs_download(datasets/openeb/aer_8bits.raw VALIDATION) + lfs_download(datasets/openeb/aer_4bits.raw VALIDATION) + lfs_download(datasets/openeb/0101_cm_mtr12_output.raw VALIDATION) + lfs_download(datasets/openeb/0101_cm_mtru_output.raw VALIDATION) if(COMPILE_PYTHON3_BINDINGS) - lfs_download(datasets/openeb/blinking_leds.raw) - lfs_download(datasets/openeb/gen4_evt2_hand_cd.dat) - lfs_download(datasets/openeb/core) + lfs_download(datasets/openeb/blinking_leds.raw VALIDATION) + lfs_download(datasets/openeb/gen4_evt2_hand_cd.dat VALIDATION) + lfs_download(datasets/openeb/core VALIDATION) endif(COMPILE_PYTHON3_BINDINGS) @@ -359,7 +361,7 @@ endforeach(metavision_modules_set) include(uninstall) include(add_library_version_header) include(add_cpack_component) -include(create_metavision_open_archive) + if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/cmake/custom_targets_metavision_sdk") list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/custom_targets_metavision_sdk) include(create_metavision_sdk_source_archives) @@ -403,17 +405,13 @@ endif (METAVISION_SDK_ADVANCED_MODULES_AVAILABLE) ################################ # Utils ## ################################ -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/utils/CMakeLists.txt") - add_subdirectory(utils) -endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/utils/CMakeLists.txt") +add_subdirectory_if_exists(utils) ################################ # HAL ## ################################ add_subdirectory(hal) -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/hal_psee_plugins/CMakeLists.txt") - add_subdirectory(hal_psee_plugins) -endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/hal_psee_plugins/CMakeLists.txt") +add_subdirectory_if_exists(hal_psee_plugins) ################################ # SDK ## @@ -428,9 +426,7 @@ add_subdirectory(standalone_samples) ################################ # Standalone apps ## ################################ -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/standalone_apps/CMakeLists.txt") - add_subdirectory(standalone_apps) -endif (EXISTS "${CMAKE_CURRENT_LIST_DIR}/standalone_apps/CMakeLists.txt") +add_subdirectory_if_exists(standalone_apps) ################################ # Documentation ## @@ -443,6 +439,9 @@ endif (GENERATE_DOC) # Add script generation at the end, once all other subdirs have been processed add_subdirectory(utils/scripts) +# Add open archive task after modules, hal and plugins that might affect it +include(create_metavision_open_archive) + ################################################### CPack for debian packages include(deb_packages) @@ -463,4 +462,3 @@ foreach(comp ${cpack_all_components}) ) endif() endforeach() - diff --git a/README.md b/README.md index 776ce9995..f39925191 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # OpenEB -OpenEB is the open source project associated with [Metavision SDK](https://www.prophesee.ai/metavision-intelligence/) +OpenEB is the open source project associated with [Metavision SDK](https://docs.prophesee.ai/stable/index.html) It enables anyone to get a better understanding of event-based vision, directly interact with events and build -their own applications or plugins. As a camera manufacturer, ensure your customers benefit from the most advanced +their own applications or camera plugins. As a camera manufacturer, ensure your customers benefit from the most advanced event-based software suite available by building your own plugin. As a creator, scientist, academic, join and contribute to the fast-growing event-based vision community. -OpenEB is composed of the Open modules of Metavision SDK: +OpenEB is composed of the [Open modules of Metavision SDK](https://docs.prophesee.ai/stable/modules.html#chapter-modules-and-packaging-open): * HAL: Hardware Abstraction Layer to operate any event-based vision device. * Base: Foundations and common definitions of event-based applications. * Core: Generic algorithms for visualization, event stream manipulation, applicative pipeline generation. @@ -15,10 +15,11 @@ OpenEB is composed of the Open modules of Metavision SDK: * Driver: High-level abstraction built on the top of HAL to easily interact with event-based cameras. * UI: Viewer and display controllers for event-based data. -OpenEB also contains the source code of Prophesee camera plugins, enabling to stream data from our event-based cameras -and to read recordings of event-based data. The supported cameras are: -* EVK2 - Gen4.1 HD -* EVK3 - Gen 3.1 VGA / Gen4.1 HD +OpenEB also contains the source code of [Prophesee camera plugins](https://docs.prophesee.ai/stable/installation/camera_plugins.html), +enabling to stream data from our event-based cameras and to read recordings of event-based data. +The supported cameras are: +* EVK2 - HD +* EVK3 - VGA/320/HD * EVK4 - HD This document describes how to compile and install the OpenEB codebase. @@ -45,7 +46,8 @@ was not tested. For those platforms some adjustments to this guide or to the cod ### Upgrading OpenEB If you are upgrading OpenEB from a previous version, you should first read carefully the [Release Notes](https://docs.prophesee.ai/stable/release_notes.html) -as some changes may impact your usage of our SDK (e.g. API updates) and cameras (e.g. [firmware update](https://support.prophesee.ai/portal/en/kb/articles/evk-firmware-versions) might be necessary). +as some changes may impact your usage of our SDK (e.g. [API](https://docs.prophesee.ai/stable/api.html) updates) +and cameras (e.g. [firmware update](https://support.prophesee.ai/portal/en/kb/articles/evk-firmware-versions) might be necessary). Then, you need to clean your system from previously installed Prophesee software. If after a previous compilation, you chose to deploy the Metavision files in your system path, then go to the `build` folder in the source code directory and @@ -65,7 +67,7 @@ Install the following dependencies: ```bash sudo apt update sudo apt -y install apt-utils build-essential software-properties-common wget unzip curl git cmake -sudo apt -y install libopencv-dev libboost-all-dev libusb-1.0-0-dev +sudo apt -y install libopencv-dev libboost-all-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler sudo apt -y install libhdf5-dev hdf5-tools libglew-dev libglfw3-dev libcanberra-gtk-module ffmpeg ``` @@ -76,7 +78,7 @@ For more details, see [Google Test User Guide](https://google.github.io/googlete sudo apt -y install libgtest-dev libgmock-dev ``` -For the Python API, you will need Python and some additional libraries. +For the [Python API](https://docs.prophesee.ai/stable/api/python/index.html#chapter-api-python), you will need Python and some additional libraries. If Python is not available on your system, install it We support Python 3.8 and 3.9 on Ubuntu 20.04 and Python 3.9 and 3.10 on Ubuntu 22.04. If you want to use other versions of Python, some source code modifications will be necessary @@ -86,7 +88,7 @@ Then install `pip` and some Python libraries: sudo apt -y install python3-pip python3-distutils sudo apt -y install python3.X-dev # where X is 8, 9 or 10 depending on your Python version (3.8, 3.9 or 3.10) python3 -m pip install pip --upgrade -python3 -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" pandas scipy h5py +python3 -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" "h5py==3.7.0" pandas scipy python3 -m pip install jupyter jupyterlab matplotlib "ipywidgets==7.6.5" pytest command_runner ``` @@ -131,7 +133,7 @@ python3 -m pip install "numba==0.56.3" "profilehooks==1.12.0" "pytorch_lightning ### Compilation - 1. Retrieve the code `git clone https://github.com/prophesee-ai/openeb.git --branch 4.3.0`. + 1. Retrieve the code: `git clone https://github.com/prophesee-ai/openeb.git --branch 4.4.0`. (If you choose to download an archive of OpenEB from GitHub rather than cloning the repository, you need to ensure that you select a ``Full.Source.Code.*`` archive instead of using the automatically generated ``Source.Code.*`` archives. This is because the latter do not include @@ -155,8 +157,8 @@ or you can deploy the OpenEB files in the system path (`/usr/local/lib`, `/usr/l source utils/scripts/setup_env.sh ``` - * Prophesee camera plugins are included in OpenEB, but you still need to copy the udev rules files in the system path - and reload them so that your camera is detected with this command: + * [Prophesee camera plugins](https://docs.prophesee.ai/stable/installation/camera_plugins.html) are included in OpenEB, + but you still need to copy the udev rules files in the system path and reload them so that your camera is detected with this command: ```bash sudo cp /hal_psee_plugins/resources/rules/*.rules /etc/udev/rules.d @@ -182,7 +184,7 @@ or you can deploy the OpenEB files in the system path (`/usr/local/lib`, `/usr/l ```bash export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib - export HDF5_PLUGIN_PATH=$HDF5_PLUGIN_PATH:/usr/local/hdf5/lib/plugin + export HDF5_PLUGIN_PATH=$HDF5_PLUGIN_PATH:/usr/local/lib/hdf5/plugin ``` Note that if you are using a third-party camera, you need to install the plugin provided @@ -222,7 +224,8 @@ For those platforms some adjustments to this guide or to the code itself may be ### Upgrading OpenEB If you are upgrading OpenEB from a previous version, you should first read carefully the [Release Notes](https://docs.prophesee.ai/stable/release_notes.html) -as some changes may impact your usage of our SDK (e.g. :API updates) and cameras (e.g. [firmware update](https://support.prophesee.ai/portal/en/kb/articles/evk-firmware-versions) might be necessary). +as some changes may impact your usage of our SDK (e.g. [API](https://docs.prophesee.ai/stable/api.html) updates) +and cameras (e.g. [firmware update](https://support.prophesee.ai/portal/en/kb/articles/evk-firmware-versions) might be necessary). Then, if you have previously installed any Prophesee's software, you will need to uninstall it first. Remove the folders where you installed Metavision artifacts (check both the `build` folder of the source code and @@ -288,7 +291,7 @@ Then install `pip` and some Python libraries: ```bash python -m pip install pip --upgrade -python -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" pandas scipy h5py +python -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" "h5py==3.7.0" pandas scipy python -m pip install jupyter jupyterlab matplotlib "ipywidgets==7.6.5" pytest command_runner ``` @@ -323,7 +326,7 @@ python -m pip install "numba==0.56.3" "profilehooks==1.12.0" "pytorch_lightning= First, retrieve the codebase: ```bash -git clone https://github.com/prophesee-ai/openeb.git --branch 4.3.0 +git clone https://github.com/prophesee-ai/openeb.git --branch 4.4.0 ``` Note that if you choose to download an archive of OpenEB from GitHub rather than cloning the repository, @@ -407,7 +410,7 @@ or you can deploy the OpenEB files (applications, samples, libraries etc.) in a #### Camera Plugins -Since OpenEB 3.0.0, **Prophesee camera plugins** are included in OpenEB, but you need to install the drivers +Prophesee camera plugins are included in OpenEB, but you need to install the drivers for the cameras to be available on Windows. To do so, follow this procedure: 1. download [wdi-simple.exe from our file server](https://files.prophesee.ai/share/dists/public/drivers/FeD45ki5/wdi-simple.exe) @@ -431,9 +434,6 @@ To get started with OpenEB, you can download some [sample recordings](https://do and visualize them with [metavision_viewer](https://docs.prophesee.ai/stable/samples/modules/driver/viewer.html) or you can stream data from your Prophesee-compatible event-based camera. -*Note* that since OpenEB 3.0.0, Prophesee camera plugins are included in the OpenEB repository, so you don't need to perform -any extra step to install them. If you are using a third-party camera, you need to install the plugin provided -by the camera vendor and specify the location of the plugin using the `MV_HAL_PLUGIN_PATH` environment variable. ### Running the test suite (Optional) diff --git a/cmake/custom_functions/add_android_app.cmake b/cmake/custom_functions/add_android_app.cmake index d39ddb0db..9ee1f3e8c 100644 --- a/cmake/custom_functions/add_android_app.cmake +++ b/cmake/custom_functions/add_android_app.cmake @@ -41,7 +41,7 @@ function(add_android_app app) # Unpack gradle cache for faster and consistent builds set(ANDROID_GRADLE_CACHE_ARCHIVE utils/android/gradle-cache.tar.gz) if (NOT EXISTS ${ANDROID_GRADLE_CACHE_DIR}) - lfs_download(${ANDROID_GRADLE_CACHE_ARCHIVE}) + lfs_download(${ANDROID_GRADLE_CACHE_ARCHIVE} COMPILATION) message(STATUS "Unpacking ${ANDROID_GRADLE_CACHE_ARCHIVE} in ${ANDROID_GRADLE_CACHE_EXTRACT_DIR}") file(MAKE_DIRECTORY ${ANDROID_GRADLE_CACHE_EXTRACT_DIR}) execute_process( diff --git a/cmake/custom_functions/add_library_version_header.cmake b/cmake/custom_functions/add_library_version_header.cmake index 4e8f180ad..d3b16d1f8 100644 --- a/cmake/custom_functions/add_library_version_header.cmake +++ b/cmake/custom_functions/add_library_version_header.cmake @@ -8,8 +8,8 @@ # See the License for the specific language governing permissions and limitations under the License. set(GIT_BRANCH "main") -set(GIT_COMMIT_ID "dd32fa23b19dfefe5da2a0d16939dd0d958fe9cf") -set(GIT_COMMIT_DATE "2023-08-07 18:30:56 +0200") +set(GIT_COMMIT_ID "5319a6deae077ed1dca071af6d1006936339e02a") +set(GIT_COMMIT_DATE "2023-10-10 17:53:39 +0200") find_program(GIT_SCM git DOC "Git version control" HINTS "C:\\Program Files\\Git\\bin\\") diff --git a/hal/cpp/apps/CMakeLists.txt b/cmake/custom_functions/common_macros.cmake similarity index 76% rename from hal/cpp/apps/CMakeLists.txt rename to cmake/custom_functions/common_macros.cmake index 62e10a990..ab81b7d20 100644 --- a/hal/cpp/apps/CMakeLists.txt +++ b/cmake/custom_functions/common_macros.cmake @@ -7,4 +7,8 @@ # 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. -add_subdirectory(metavision_platform_info) \ No newline at end of file +macro(add_subdirectory_if_exists sub_dir) + if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${sub_dir}/CMakeLists.txt") + add_subdirectory(${sub_dir}) + endif() +endmacro() diff --git a/cmake/custom_functions/lfs_download.cmake b/cmake/custom_functions/lfs_download.cmake index e3afb8b00..a07e216c0 100644 --- a/cmake/custom_functions/lfs_download.cmake +++ b/cmake/custom_functions/lfs_download.cmake @@ -9,30 +9,55 @@ set(GIT_LFS_NOT_AVAILABLE True) +include(CMakeParseArguments) +option(LFS_DOWNLOAD_COMPILATION_RESOURCES "Only download LFS resources required for compilation step" ON) +option(LFS_DOWNLOAD_VALIDATION_RESOURCES "Only download LFS resources required for compilation step" ON) + # Function to download files or directories with git lfs # # Usage: # lfs_download(file_path|dir_path [file_path|dir_path]) function(lfs_download) - if (${ARGC} GREATER 0) - string(REPLACE ";" ", " file_or_dir_to_download_comma_separated "${ARGN}") - if (NOT GIT_LFS_NOT_AVAILABLE) - foreach(file_or_dir_to_download ${ARGN}) - if(NOT EXISTS "${PROJECT_SOURCE_DIR}/${file_or_dir_to_download}") - message(FATAL_ERROR "${PROJECT_SOURCE_DIR}/${file_or_dir_to_download} does not exist") - endif() - endforeach(file_or_dir_to_download) - message(STATUS "Downloading ${file_or_dir_to_download_comma_separated} with lfs") - execute_process( - COMMAND git lfs pull --include "${file_or_dir_to_download_comma_separated}" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE OUTUT - ERROR_VARIABLE ERROR - RESULT_VARIABLE RESULT - ) - if (RESULT AND NOT RESULT EQUAL 0) - message(FATAL_ERROR "lfs_download error : ${ERROR} output : ${OUTPUT}") - endif () - endif (NOT GIT_LFS_NOT_AVAILABLE) + cmake_parse_arguments(LFS_DOWNLOAD_ARGS "VALIDATION;COMPILATION" "" "" ${ARGN}) + if (NOT LFS_DOWNLOAD_ARGS_VALIDATION AND NOT LFS_DOWNLOAD_ARGS_COMPILATION) + message(FATAL_ERROR "lfs_download must be called with at least one keyword in [COMPILATION,VALIDATION]") + endif () + if (NOT LFS_DOWNLOAD_ARGS_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "lfs_download must be called with a list of files/dirs") endif () + string(REPLACE ";" ", " file_or_dir_to_download_comma_separated "${LFS_DOWNLOAD_ARGS_UNPARSED_ARGUMENTS}") + if (NOT GIT_LFS_NOT_AVAILABLE) + foreach(file_or_dir_to_download ${LFS_DOWNLOAD_ARGS_UNPARSED_ARGUMENTS}) + if(NOT EXISTS "${PROJECT_SOURCE_DIR}/${file_or_dir_to_download}") + message(FATAL_ERROR "${PROJECT_SOURCE_DIR}/${file_or_dir_to_download} does not exist") + endif() + endforeach(file_or_dir_to_download) + + if ((LFS_DOWNLOAD_ARGS_COMPILATION AND LFS_DOWNLOAD_COMPILATION_RESOURCES) OR (LFS_DOWNLOAD_ARGS_VALIDATION AND LFS_DOWNLOAD_VALIDATION_RESOURCES)) + message(STATUS "Downloading ${file_or_dir_to_download_comma_separated} with lfs") + set(retries 3) + set(success FALSE) + while (NOT success AND retries GREATER 0) + execute_process( + COMMAND git lfs pull --include "${file_or_dir_to_download_comma_separated}" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE OUTPUT + ERROR_VARIABLE ERROR + RESULT_VARIABLE RESULT + ) + if (RESULT AND NOT RESULT EQUAL 0) + message(WARNING "lfs_download error : ${ERROR} output : ${OUTPUT}") + math(EXPR retries "${retries} - 1") + if (retries GREATER 0) + message(STATUS "Retrying download of ${file_or_dir_to_download_comma_separated}") + endif () + else() + set(success TRUE) + endif() + endwhile() + if (NOT success) + message(FATAL_ERROR "lfs_download failed after 3 retries") + endif() + endif () + endif (NOT GIT_LFS_NOT_AVAILABLE) endfunction() diff --git a/cmake/custom_targets/README_metavision_open.md b/cmake/custom_targets/README_metavision_open.md index 776ce9995..f39925191 100644 --- a/cmake/custom_targets/README_metavision_open.md +++ b/cmake/custom_targets/README_metavision_open.md @@ -1,13 +1,13 @@ # OpenEB -OpenEB is the open source project associated with [Metavision SDK](https://www.prophesee.ai/metavision-intelligence/) +OpenEB is the open source project associated with [Metavision SDK](https://docs.prophesee.ai/stable/index.html) It enables anyone to get a better understanding of event-based vision, directly interact with events and build -their own applications or plugins. As a camera manufacturer, ensure your customers benefit from the most advanced +their own applications or camera plugins. As a camera manufacturer, ensure your customers benefit from the most advanced event-based software suite available by building your own plugin. As a creator, scientist, academic, join and contribute to the fast-growing event-based vision community. -OpenEB is composed of the Open modules of Metavision SDK: +OpenEB is composed of the [Open modules of Metavision SDK](https://docs.prophesee.ai/stable/modules.html#chapter-modules-and-packaging-open): * HAL: Hardware Abstraction Layer to operate any event-based vision device. * Base: Foundations and common definitions of event-based applications. * Core: Generic algorithms for visualization, event stream manipulation, applicative pipeline generation. @@ -15,10 +15,11 @@ OpenEB is composed of the Open modules of Metavision SDK: * Driver: High-level abstraction built on the top of HAL to easily interact with event-based cameras. * UI: Viewer and display controllers for event-based data. -OpenEB also contains the source code of Prophesee camera plugins, enabling to stream data from our event-based cameras -and to read recordings of event-based data. The supported cameras are: -* EVK2 - Gen4.1 HD -* EVK3 - Gen 3.1 VGA / Gen4.1 HD +OpenEB also contains the source code of [Prophesee camera plugins](https://docs.prophesee.ai/stable/installation/camera_plugins.html), +enabling to stream data from our event-based cameras and to read recordings of event-based data. +The supported cameras are: +* EVK2 - HD +* EVK3 - VGA/320/HD * EVK4 - HD This document describes how to compile and install the OpenEB codebase. @@ -45,7 +46,8 @@ was not tested. For those platforms some adjustments to this guide or to the cod ### Upgrading OpenEB If you are upgrading OpenEB from a previous version, you should first read carefully the [Release Notes](https://docs.prophesee.ai/stable/release_notes.html) -as some changes may impact your usage of our SDK (e.g. API updates) and cameras (e.g. [firmware update](https://support.prophesee.ai/portal/en/kb/articles/evk-firmware-versions) might be necessary). +as some changes may impact your usage of our SDK (e.g. [API](https://docs.prophesee.ai/stable/api.html) updates) +and cameras (e.g. [firmware update](https://support.prophesee.ai/portal/en/kb/articles/evk-firmware-versions) might be necessary). Then, you need to clean your system from previously installed Prophesee software. If after a previous compilation, you chose to deploy the Metavision files in your system path, then go to the `build` folder in the source code directory and @@ -65,7 +67,7 @@ Install the following dependencies: ```bash sudo apt update sudo apt -y install apt-utils build-essential software-properties-common wget unzip curl git cmake -sudo apt -y install libopencv-dev libboost-all-dev libusb-1.0-0-dev +sudo apt -y install libopencv-dev libboost-all-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler sudo apt -y install libhdf5-dev hdf5-tools libglew-dev libglfw3-dev libcanberra-gtk-module ffmpeg ``` @@ -76,7 +78,7 @@ For more details, see [Google Test User Guide](https://google.github.io/googlete sudo apt -y install libgtest-dev libgmock-dev ``` -For the Python API, you will need Python and some additional libraries. +For the [Python API](https://docs.prophesee.ai/stable/api/python/index.html#chapter-api-python), you will need Python and some additional libraries. If Python is not available on your system, install it We support Python 3.8 and 3.9 on Ubuntu 20.04 and Python 3.9 and 3.10 on Ubuntu 22.04. If you want to use other versions of Python, some source code modifications will be necessary @@ -86,7 +88,7 @@ Then install `pip` and some Python libraries: sudo apt -y install python3-pip python3-distutils sudo apt -y install python3.X-dev # where X is 8, 9 or 10 depending on your Python version (3.8, 3.9 or 3.10) python3 -m pip install pip --upgrade -python3 -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" pandas scipy h5py +python3 -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" "h5py==3.7.0" pandas scipy python3 -m pip install jupyter jupyterlab matplotlib "ipywidgets==7.6.5" pytest command_runner ``` @@ -131,7 +133,7 @@ python3 -m pip install "numba==0.56.3" "profilehooks==1.12.0" "pytorch_lightning ### Compilation - 1. Retrieve the code `git clone https://github.com/prophesee-ai/openeb.git --branch 4.3.0`. + 1. Retrieve the code: `git clone https://github.com/prophesee-ai/openeb.git --branch 4.4.0`. (If you choose to download an archive of OpenEB from GitHub rather than cloning the repository, you need to ensure that you select a ``Full.Source.Code.*`` archive instead of using the automatically generated ``Source.Code.*`` archives. This is because the latter do not include @@ -155,8 +157,8 @@ or you can deploy the OpenEB files in the system path (`/usr/local/lib`, `/usr/l source utils/scripts/setup_env.sh ``` - * Prophesee camera plugins are included in OpenEB, but you still need to copy the udev rules files in the system path - and reload them so that your camera is detected with this command: + * [Prophesee camera plugins](https://docs.prophesee.ai/stable/installation/camera_plugins.html) are included in OpenEB, + but you still need to copy the udev rules files in the system path and reload them so that your camera is detected with this command: ```bash sudo cp /hal_psee_plugins/resources/rules/*.rules /etc/udev/rules.d @@ -182,7 +184,7 @@ or you can deploy the OpenEB files in the system path (`/usr/local/lib`, `/usr/l ```bash export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib - export HDF5_PLUGIN_PATH=$HDF5_PLUGIN_PATH:/usr/local/hdf5/lib/plugin + export HDF5_PLUGIN_PATH=$HDF5_PLUGIN_PATH:/usr/local/lib/hdf5/plugin ``` Note that if you are using a third-party camera, you need to install the plugin provided @@ -222,7 +224,8 @@ For those platforms some adjustments to this guide or to the code itself may be ### Upgrading OpenEB If you are upgrading OpenEB from a previous version, you should first read carefully the [Release Notes](https://docs.prophesee.ai/stable/release_notes.html) -as some changes may impact your usage of our SDK (e.g. :API updates) and cameras (e.g. [firmware update](https://support.prophesee.ai/portal/en/kb/articles/evk-firmware-versions) might be necessary). +as some changes may impact your usage of our SDK (e.g. [API](https://docs.prophesee.ai/stable/api.html) updates) +and cameras (e.g. [firmware update](https://support.prophesee.ai/portal/en/kb/articles/evk-firmware-versions) might be necessary). Then, if you have previously installed any Prophesee's software, you will need to uninstall it first. Remove the folders where you installed Metavision artifacts (check both the `build` folder of the source code and @@ -288,7 +291,7 @@ Then install `pip` and some Python libraries: ```bash python -m pip install pip --upgrade -python -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" pandas scipy h5py +python -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" "h5py==3.7.0" pandas scipy python -m pip install jupyter jupyterlab matplotlib "ipywidgets==7.6.5" pytest command_runner ``` @@ -323,7 +326,7 @@ python -m pip install "numba==0.56.3" "profilehooks==1.12.0" "pytorch_lightning= First, retrieve the codebase: ```bash -git clone https://github.com/prophesee-ai/openeb.git --branch 4.3.0 +git clone https://github.com/prophesee-ai/openeb.git --branch 4.4.0 ``` Note that if you choose to download an archive of OpenEB from GitHub rather than cloning the repository, @@ -407,7 +410,7 @@ or you can deploy the OpenEB files (applications, samples, libraries etc.) in a #### Camera Plugins -Since OpenEB 3.0.0, **Prophesee camera plugins** are included in OpenEB, but you need to install the drivers +Prophesee camera plugins are included in OpenEB, but you need to install the drivers for the cameras to be available on Windows. To do so, follow this procedure: 1. download [wdi-simple.exe from our file server](https://files.prophesee.ai/share/dists/public/drivers/FeD45ki5/wdi-simple.exe) @@ -431,9 +434,6 @@ To get started with OpenEB, you can download some [sample recordings](https://do and visualize them with [metavision_viewer](https://docs.prophesee.ai/stable/samples/modules/driver/viewer.html) or you can stream data from your Prophesee-compatible event-based camera. -*Note* that since OpenEB 3.0.0, Prophesee camera plugins are included in the OpenEB repository, so you don't need to perform -any extra step to install them. If you are using a third-party camera, you need to install the plugin provided -by the camera vendor and specify the location of the plugin using the `MV_HAL_PLUGIN_PATH` environment variable. ### Running the test suite (Optional) diff --git a/cmake/custom_targets/create_metavision_open_archive.cmake b/cmake/custom_targets/create_metavision_open_archive.cmake index 2d6e0a01d..d50b91417 100644 --- a/cmake/custom_targets/create_metavision_open_archive.cmake +++ b/cmake/custom_targets/create_metavision_open_archive.cmake @@ -9,8 +9,10 @@ set(output_metavision_open_archive_dir_path "${GENERATE_FILES_DIRECTORY}/metavision_open_archive") set(output_metavision_open_full_archive_dir_path "${GENERATE_FILES_DIRECTORY}/metavision_open_full_archive") + add_custom_target(create_metavision_open_archive_folder COMMAND ${CMAKE_COMMAND} + -DHAL_OPEN_PLUGIN_DEVICES="${HAL_PSEE_OPEN_PLUGIN_DEVICES}" -DPROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}" -DOUTPUT_DIR="${output_metavision_open_archive_dir_path}" -DGIT_COMMAND_GET_BRANCH="${GIT_COMMAND_GET_BRANCH}" @@ -20,6 +22,7 @@ add_custom_target(create_metavision_open_archive_folder -DGENERATE_FILES_DIRECTORY="${GENERATE_FILES_DIRECTORY}" -P ${CMAKE_CURRENT_LIST_DIR}/create_metavision_open_archive_folder.cmake COMMAND ${CMAKE_COMMAND} + -DHAL_OPEN_PLUGIN_DEVICES="${HAL_PSEE_OPEN_PLUGIN_DEVICES}" -DPROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}" -DOUTPUT_DIR="${output_metavision_open_full_archive_dir_path}/openeb-${PROJECT_VERSION_FULL}" -DGIT_COMMAND_GET_BRANCH="${GIT_COMMAND_GET_BRANCH}" @@ -42,4 +45,4 @@ add_custom_target(create_metavision_open_archive COMMAND ${CMAKE_COMMAND} -E chdir ${output_metavision_open_full_archive_dir_path} ${CMAKE_COMMAND} -E tar cvf ${output_metavision_open_full_zip_archive_path} --format=zip . COMMAND ${CMAKE_COMMAND} -E echo "File ${output_metavision_open_full_zip_archive_path} generated" ) -add_dependencies(create_metavision_open_archive create_metavision_open_archive_folder) \ No newline at end of file +add_dependencies(create_metavision_open_archive create_metavision_open_archive_folder) diff --git a/cmake/custom_targets/create_metavision_open_archive_folder.cmake b/cmake/custom_targets/create_metavision_open_archive_folder.cmake index 5b913b9c2..b8f9aba32 100644 --- a/cmake/custom_targets/create_metavision_open_archive_folder.cmake +++ b/cmake/custom_targets/create_metavision_open_archive_folder.cmake @@ -14,13 +14,14 @@ file(MAKE_DIRECTORY "${OUTPUT_DIR}") # For some reason, CMAKE_MODULE_PATH passed by create_metavision_open_archive # has spaces instead of semicolumns string(REPLACE " " ";" CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}") +string(REPLACE " " ";" HAL_OPEN_PLUGIN_DEVICES "${HAL_OPEN_PLUGIN_DEVICES}") + include(overridden_cmake_functions) set(HAL_OPEN_PLUGIN_FILES apps biasgen cmake CMakeLists.txt lib resources samples test) set(HAL_OPEN_PLUGIN_INCLUDES boards utils geometries plugin devices/common devices/utils devices/others) set(HAL_OPEN_PLUGIN_HW_LAYER_INCLUDES boards facilities utils devices/common devices/utils devices/psee-video) set(HAL_OPEN_PLUGIN_SOURCES boards CMakeLists.txt facilities plugin utils devices/common devices/utils devices/psee-video devices/others devices/CMakeLists.txt) -set(HAL_OPEN_PLUGIN_DEVICES gen31 gen41 imx636 imx646 genx320 treuzell) foreach (open_device ${HAL_OPEN_PLUGIN_DEVICES}) list(APPEND HAL_OPEN_PLUGIN_INCLUDES devices/${open_device}) @@ -83,6 +84,9 @@ endif () # Remove Metavision Studio : file(REMOVE_RECURSE "${OUTPUT_DIR}/sdk/modules/core/cpp/apps/metavision_studio") +# Remove evk3d viewer as the plugin is closed source +file(REMOVE_RECURSE "${OUTPUT_DIR}/sdk/modules/driver/cpp/samples/metavision_evk3d_viewer") + # Now we need to modify the way to determine the VCS information (folder created is not be a git repo) string(CONCAT licence_header "# Copyright (c) Prophesee S.A.\n" "#\n" diff --git a/hal/cpp/CMakeLists.txt b/hal/cpp/CMakeLists.txt index a4dfee2ec..c23be9004 100644 --- a/hal/cpp/CMakeLists.txt +++ b/hal/cpp/CMakeLists.txt @@ -40,8 +40,7 @@ add_subdirectory(lib) # Add sources to the libraries and plugins add_subdirectory(src) -# Apps and samples -add_subdirectory(apps) +# Samples add_subdirectory(samples) # Tests diff --git a/hal/cpp/include/metavision/hal/decoders/mtr/mtr_decoder.h b/hal/cpp/include/metavision/hal/decoders/mtr/mtr_decoder.h new file mode 100644 index 000000000..e70501941 --- /dev/null +++ b/hal/cpp/include/metavision/hal/decoders/mtr/mtr_decoder.h @@ -0,0 +1,229 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_MTR_DECODER_H +#define METAVISION_HAL_MTR_DECODER_H + +#include +#include +#include + +#include +#include +#include +#include + +namespace Metavision { + +class MTRDecoder : public I_EventFrameDecoder { +public: + enum MTRMode { MTR, MTRMetric, MTRHomogeneous, MTRScaled, MTRHomogeneousScaled }; + + /// @brief Constructor + /// @param sensor_width Width of the sensor + /// @param sensor_height Height of the sensor + /// @param mode MTR (Module for Triangulation) stream mode + MTRDecoder(int sensor_width = 1280, int sensor_height = 720, MTRMode mode = MTRMode::MTR) : + I_EventFrameDecoder(sensor_height, sensor_width), mode_(mode) {} + + virtual ~MTRDecoder() {} + + /// @brief Gets size of a raw event in bytes + uint8_t get_raw_event_size_bytes() const override { + switch (mode_) { + case MTRMode::MTRMetric: + case MTRMode::MTRHomogeneous: + case MTRMode::MTRScaled: + case MTRMode::MTRHomogeneousScaled: + return sizeof(Evt_MTRU); + default: + return sizeof(Evt_MTR); + } + } + + void decode(const RawData *ev_bufferp, const RawData *evendp) override { + switch (mode_) { + case MTRMode::MTRMetric: + decode_impl_MTRU(ev_bufferp, evendp, [this](uint32_t X, uint32_t Y, uint32_t Z, int ch_id, int rep_id) { + int32_t xs = X & (1 << 15) ? X | 0xFFFF0000 : X; + int32_t ys = Y & (1 << 15) ? Y | 0xFFFF0000 : Y; + PointCloud::Point3D pt = {xs / ((float)(1 << 11)), ys / ((float)(1 << 11)), Z / ((float)(1 << 12)), + ch_id, rep_id}; + return pt; + }); + break; + case MTRMode::MTRHomogeneous: + decode_impl_MTRU(ev_bufferp, evendp, [](uint32_t X, uint32_t Y, uint32_t Z, int ch_id, int rep_id) { + int32_t xs = X & (1 << 15) ? X | 0xFFFF0000 : X; + int32_t ys = Y & (1 << 15) ? Y | 0xFFFF0000 : Y; + float Zf = Z / ((float)(1 << 12)); + PointCloud::Point3D pt = {xs * Zf / ((float)(1 << 15)), ys * Zf / ((float)(1 << 15)), Zf, ch_id, + rep_id}; + return pt; + }); + break; + case MTRMode::MTRHomogeneousScaled: + decode_impl_MTRU(ev_bufferp, evendp, [this](uint32_t X, uint32_t Y, uint32_t Z, int ch_id, int rep_id) { + int32_t xs = X & (1 << 15) ? X | 0xFFFF0000 : X; + int32_t ys = Y & (1 << 15) ? Y | 0xFFFF0000 : Y; + int32_t zs = Z & (1 << 15) ? Z | 0xFFFF0000 : Z; + float Zf = zs * Z_max_ / ((float)(1 << 15)); + PointCloud::Point3D pt = {xs * Zf * X_max_ / ((float)(1 << 15)), ys * Zf * Y_max_ / ((float)(1 << 15)), + Zf, ch_id, rep_id}; + return pt; + }); + break; + case MTRMode::MTRScaled: + decode_impl_MTRU(ev_bufferp, evendp, [this](uint32_t X, uint32_t Y, uint32_t Z, int ch_id, int rep_id) { + int32_t xs = X & (1 << 15) ? X | 0xFFFF0000 : X; + int32_t ys = Y & (1 << 15) ? Y | 0xFFFF0000 : Y; + PointCloud::Point3D pt = {xs * X_max_ / ((float)(1 << 15)), ys * Y_max_ / ((float)(1 << 15)), + Z * Z_max_ / ((float)(1 << 15)), ch_id, rep_id}; + return pt; + }); + break; + default: + decode_impl_MTRPixel(ev_bufferp, evendp); + break; + } + } + +private: + struct Evt_MTR { + uint64_t Z : 19; + uint64_t y : 10; + uint64_t x : 15; + uint64_t padding1 : 4; + uint64_t channel_number : 3; + uint64_t padding2 : 1; + uint64_t repetition_id : 3; + uint64_t padding3 : 1; + uint64_t frame_number : 7; + uint64_t padding4 : 1; + }; + + struct Evt_MTRU { + uint32_t Z : 16; + uint32_t Y : 16; + uint32_t X : 16; + uint32_t channel_number : 3; + uint32_t padding2 : 1; + uint32_t repetition_id : 3; + uint32_t padding3 : 1; + uint32_t frame_number : 7; + uint32_t padding4 : 1; + }; + + static_assert(sizeof(Evt_MTR) == 8, "The size of the packed struct Evt_MTR is not expected one (which is 8 bytes)"); + static_assert(sizeof(Evt_MTRU) == 8, + "The size of the packed struct Evt_MTRU is not expected one (which is 8 bytes)"); + + void decode_impl_MTRPixel(const RawData *ev_bufferp, const RawData *evendp) { + const Evt_MTR *cur_ev = reinterpret_cast(ev_bufferp); + const Evt_MTR *ev_end = reinterpret_cast(evendp); + + for (; cur_ev < ev_end; ++cur_ev) { + const unsigned int ev_ch_num = cur_ev->channel_number; + const unsigned int ev_frame_num = cur_ev->frame_number; + // Check first if we are changing channel + if (ev_ch_num != cur_channel_id_) { + // Check correct increment + if (ev_ch_num < cur_channel_id_ && ev_frame_num == cur_frame_counter_) { + MV_HAL_LOG_WARNING() << "Moving from channel " << cur_channel_id_ << " to channel " << ev_ch_num + << " in the same frame." << std::endl; + } + + cur_channel_id_ = ev_ch_num; + } + // If we also changed frame, let's call the correct callback + if (ev_frame_num != cur_frame_counter_) { + // Change of frame detected, check correct increment + if (ev_frame_num - cur_frame_counter_ != 1 && !(ev_frame_num == 0 && cur_frame_counter_ == 0x07F)) { + MV_HAL_LOG_WARNING() << "Moving from frame " << cur_frame_counter_ << " to frame " << ev_frame_num + << std::endl; + } + // Keep track of new info + cur_frame_counter_ = ev_frame_num; + ++cur_frame_id_; + // Callbacks + add_event_frame({cur_frame_id_, Z_max_, std::move(pointcloud_)}); + } + // Accumulate data present in event + pointcloud_.push_back({cur_ev->x / 16.f, (float)cur_ev->y, cur_ev->Z / ((float)(1 << 15)), + (int)cur_ev->channel_number, (int)cur_ev->repetition_id}); + } + } + + void decode_impl_MTRU(const RawData *ev_bufferp, const RawData *evendp, + const std::function &Transform) { + const Evt_MTRU *cur_ev = reinterpret_cast(ev_bufferp); + const Evt_MTRU *ev_end = reinterpret_cast(evendp); + + for (; cur_ev < ev_end; ++cur_ev) { + const unsigned int ev_ch_num = cur_ev->channel_number; + const unsigned int ev_frame_num = cur_ev->frame_number; + // Check first if we are changing channel + if (ev_ch_num != cur_channel_id_) { + // Check correct increment + if (ev_ch_num < cur_channel_id_ && ev_frame_num == cur_frame_counter_) { + MV_HAL_LOG_WARNING() << "Error: Moving from channel " << cur_channel_id_ << " to channel " + << ev_ch_num << " in the same frame." << std::endl; + } + + cur_channel_id_ = ev_ch_num; + } + // If we also changed frame, let's call the correct callback + if (ev_frame_num != cur_frame_counter_) { + // Change of frame detected, check correct increment + if (ev_frame_num - cur_frame_counter_ != 1 && !(ev_frame_num == 0 && cur_frame_counter_ == 0x07F)) { + MV_HAL_LOG_WARNING() << "Error: Moving from frame " << cur_frame_counter_ << " to frame " + << ev_frame_num << std::endl; + } + // Keep track of new info + cur_frame_counter_ = ev_frame_num; + ++cur_frame_id_; + // Callbacks + add_event_frame({cur_frame_id_, Z_max_, std::move(pointcloud_)}); + } + // Accumulate data present in event + pointcloud_.emplace_back( + Transform(cur_ev->X, cur_ev->Y, cur_ev->Z, cur_ev->channel_number, cur_ev->repetition_id)); + } + } + + unsigned int cur_frame_id_ = 0; + unsigned int cur_frame_counter_ = 0; + unsigned int cur_channel_id_ = 0; + std::vector pointcloud_; + MTRMode mode_; + + const float X_max_ = 16.f, Y_max_ = 16.f, Z_max_ = 16.f; +}; + +inline std::unique_ptr mtr_decoder_from_format(const I_Geometry &geometry, const std::string &format) { + static std::map format_to_mode = { + {"MTR", MTRDecoder::MTRMode::MTR}, + {"MTRMetric", MTRDecoder::MTRMode::MTRMetric}, + {"MTRHomogeneous", MTRDecoder::MTRMode::MTRHomogeneous}, + {"MTRScaled", MTRDecoder::MTRMode::MTRScaled}, + {"MTRHomogeneousScaled", MTRDecoder::MTRMode::MTRHomogeneousScaled}}; + + if (format_to_mode.count(format) <= 0) { + return nullptr; + } + + return std::make_unique(geometry.get_width(), geometry.get_height(), format_to_mode[format]); +} + +} // namespace Metavision + +#endif /* METAVISION_HAL_MTR_DECODER_H */ diff --git a/hal/cpp/include/metavision/hal/facilities/i_decoder.h b/hal/cpp/include/metavision/hal/facilities/i_decoder.h index 02c2f1998..9968a93df 100644 --- a/hal/cpp/include/metavision/hal/facilities/i_decoder.h +++ b/hal/cpp/include/metavision/hal/facilities/i_decoder.h @@ -15,11 +15,12 @@ #include #include +#include "metavision/hal/facilities/i_registrable_facility.h" #include "metavision/hal/utils/decoder_protocol_violation.h" namespace Metavision { -class I_Decoder { +class I_Decoder : public I_RegistrableFacility { public: /// @brief Alias for raw data type using RawData = uint8_t; diff --git a/hal/cpp/include/metavision/hal/facilities/i_event_frame_decoder.h b/hal/cpp/include/metavision/hal/facilities/i_event_frame_decoder.h index b5a2b2f04..7e3202e8c 100644 --- a/hal/cpp/include/metavision/hal/facilities/i_event_frame_decoder.h +++ b/hal/cpp/include/metavision/hal/facilities/i_event_frame_decoder.h @@ -14,6 +14,8 @@ #include #include +#include +#include #include "metavision/hal/facilities/i_decoder.h" #include "metavision/hal/facilities/i_registrable_facility.h" @@ -25,7 +27,7 @@ namespace Metavision { /// This class is meant to receive raw data from the camera, and dispatch parts of the buffer to instances /// of @ref I_EventDecoder for specific event types. template -class I_EventFrameDecoder : public I_Decoder, public I_RegistrableFacility> { +class I_EventFrameDecoder : public I_RegistrableFacility, I_Decoder> { public: /// @brief Alias for raw data type using EventFrameCallback_t = std::function; @@ -51,7 +53,8 @@ class I_EventFrameDecoder : public I_Decoder, public I_RegistrableFacility get_last_frame(); + protected: /// @cond DEV void add_event_frame(const FrameType &frame); @@ -74,6 +81,9 @@ class I_EventFrameDecoder : public I_Decoder, public I_RegistrableFacility cbs_map_; size_t next_cb_idx_{0}; + + std::shared_ptr last_frame_; + std::mutex last_frame_lock_; }; template @@ -90,11 +100,23 @@ bool I_EventFrameDecoder::remove_callback(size_t callback_id) { return cbs_map_.erase(callback_id); } +template +std::shared_ptr I_EventFrameDecoder::get_last_frame() { + std::lock_guard lock(last_frame_lock_); + return last_frame_; +} + /// @cond DEV template void I_EventFrameDecoder::add_event_frame(const FrameType &frame) { + { + auto new_frame = std::make_shared(std::move(frame)); + std::lock_guard lock(last_frame_lock_); + last_frame_ = new_frame; + } + for (auto &it : cbs_map_) { - it.second(frame); + it.second(*last_frame_); } } /// @endcond diff --git a/hal/cpp/include/metavision/hal/facilities/i_event_rate_activity_filter_module.h b/hal/cpp/include/metavision/hal/facilities/i_event_rate_activity_filter_module.h new file mode 100644 index 000000000..c44ea7c2a --- /dev/null +++ b/hal/cpp/include/metavision/hal/facilities/i_event_rate_activity_filter_module.h @@ -0,0 +1,104 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_I_EVENT_RATE_ACTIVITY_FILTER_MODULE_H +#define METAVISION_HAL_I_EVENT_RATE_ACTIVITY_FILTER_MODULE_H + +#include + +#include "metavision/hal/facilities/i_registrable_facility.h" + +namespace Metavision { + +/// @brief Interface for accessing the sensor event rate activity filter. +/// +/// This sensor level filter is based on the event rate only. If enabled, the sensor will transfer data if and +/// only if the event rate is above a given event rate and below a given event rate. It avoids streaming background +/// noise information without relevant activity and streaming high event rate flashing scenes, saving bandwidth and +/// power. +class I_EventRateActivityFilterModule : public I_RegistrableFacility { +public: + /// @brief Band pass filter hysteresis thresholds for event rate activity filter + /// @note Not all thresholds are supported given the sensor generation + + /// @param lower_bound_start Event rate threshold for the band pass filter to start filtering incoming events. + /// Below this threshold, no events are streamed. + /// @param lower_bound_stop Event rate threshold for the band pass filter to stop filtering and resume streaming + /// of incoming events. + /// Above this threshold, events are streamed again after the filter was actively dropping + /// events using the @ref lower_bound_start threshold condition. + /// @param upper_bound_start Event rate threshold for the band pass filter to start filtering incoming events. + /// Above this threshold, no events are streamed. + /// @param upper_bound_stop Event rate threshold for the band pass filter to stop filtering and resume streaming + /// of incoming events. + /// Below this threshold, events are streamed again after the filter was actively dropping events using the @ref + /// upper_bound_start threshold condition. + struct thresholds { + uint32_t lower_bound_start; + uint32_t lower_bound_stop; + uint32_t upper_bound_start; + uint32_t upper_bound_stop; + }; + + /// @brief Enables/disables the event rate activity filter + /// @param enable_filter Whether to enable the filter + virtual bool enable(bool enable_filter) = 0; + + /// @brief Returns the event rate activity filter state + /// @return the filter state + virtual bool is_enabled() const = 0; + + /// @brief Sets the event rate threshold. Below this threshold, no events are streamed. + /// @param threshold_Kev_s Event rate threshold in Kevt/s + /// @return true if the input value was correctly set (i.e. it falls in the range of acceptable values for the + /// sensor) + [[deprecated("This function is deprecated starting with version 4.4.0. Please use " + "set_lower/upper_bound_threshold_start/stop() instead.")]] virtual bool + set_event_rate_threshold(uint32_t threshold_Kev_s) = 0; + + /// @brief Gets the event rate threshold in Kevt/s below which no events are streamed + /// @return Event rate threshold in Kevt/s + [[deprecated("This function is deprecated starting with version 4.4.0. Please use " + "get_lower/upper_bound_threshold_start/stop() instead.")]] virtual uint32_t + get_event_rate_threshold() const = 0; + + /// @brief Gets band pass filter hysteresis thresholds supported by the sensor. + /// @return @ref thresholds thresholds structure with values 0/1 depending if corresponding threshold is supported. + virtual thresholds is_thresholds_supported() const = 0; + + /// @brief Sets band pass filter hysteresis thresholds. + /// @param thresholds_ev_s Event rate thresholds data structure in evt/s + /// @warning Partially initialize structure \p thresholds_ev_s could lead to random threshold values being set. + /// Use @ref is_thresholds_supported function to know which threshold values could be omitted. + /// @return true if the input value was correctly set (i.e. it falls in the range of acceptable values for the + /// sensor) + virtual bool set_thresholds(const thresholds &thresholds_ev_s) = 0; + + /// @brief Gets band pass filter hysteresis thresholds. + /// @return @ref thresholds event rate thresholds structure. + virtual thresholds get_thresholds() const = 0; + + /// @brief Gets band pass filter hysteresis minimum thresholds configuration. + /// @return @ref thresholds event rate thresholds structure. + virtual thresholds get_min_supported_thresholds() const = 0; + + /// @brief Gets band pass filter hysteresis maximum thresholds configuration. + /// @return @ref thresholds event rate thresholds structure. + virtual thresholds get_max_supported_thresholds() const = 0; +}; + +using I_EventRateNoiseFilterModule [[deprecated( + "This class name is deprecated starting version 4.4.0. Please use I_EventRateActivityFilterModule instead.")]] = + I_EventRateActivityFilterModule; + +} // namespace Metavision + +#endif // METAVISION_HAL_I_EVENT_RATE_ACTIVITY_FILTER_MODULE_H diff --git a/hal/cpp/include/metavision/hal/facilities/i_events_stream_decoder.h b/hal/cpp/include/metavision/hal/facilities/i_events_stream_decoder.h index 9da5d1ef3..b4edcc7ec 100644 --- a/hal/cpp/include/metavision/hal/facilities/i_events_stream_decoder.h +++ b/hal/cpp/include/metavision/hal/facilities/i_events_stream_decoder.h @@ -32,7 +32,7 @@ namespace Metavision { /// /// This class is meant to receive raw data from the camera, and dispatch parts of the buffer to instances /// of @ref I_EventDecoder for specific event types. -class I_EventsStreamDecoder : public I_Decoder, public I_RegistrableFacility { +class I_EventsStreamDecoder : public I_RegistrableFacility { public: /// @brief Alias for callback on timestamp using TimeCallback_t = std::function; diff --git a/hal/cpp/include/metavision/hal/facilities/i_roi.h b/hal/cpp/include/metavision/hal/facilities/i_roi.h index ca5db199f..b170292a0 100644 --- a/hal/cpp/include/metavision/hal/facilities/i_roi.h +++ b/hal/cpp/include/metavision/hal/facilities/i_roi.h @@ -56,6 +56,10 @@ class I_ROI : public I_RegistrableFacility { /// @return true on success virtual bool enable(bool state) = 0; + /// @brief Returns ROI/RONI activation state + /// @return The ROI/RONI state + virtual bool is_enabled() const = 0; + /// @brief Window mode /// /// ROI : Region of interest, any event outside the window will be discarded @@ -67,6 +71,10 @@ class I_ROI : public I_RegistrableFacility { /// @return true on success virtual bool set_mode(const Mode &mode) = 0; + /// @brief Gets the window mode + /// @return the window mode + virtual Mode get_mode() const = 0; + /// @brief Sets a window /// /// The window will be applied according to the current mode (ROI or RONI) @@ -90,6 +98,11 @@ class I_ROI : public I_RegistrableFacility { /// of windows (see @ref get_max_supported_windows_count) bool set_windows(const std::vector &windows); + /// @brief Gets active ROI/RONI windows + /// + /// @return The vector of active windows + virtual std::vector get_windows() const = 0; + /// @brief Sets multiple lines and columns from row and column binary maps /// /// The binary maps (std::vector) arguments must have the sensor's dimension. diff --git a/hal/cpp/include/metavision/hal/facilities/i_roi_pixel_mask.h b/hal/cpp/include/metavision/hal/facilities/i_roi_pixel_mask.h new file mode 100644 index 000000000..f35c999e9 --- /dev/null +++ b/hal/cpp/include/metavision/hal/facilities/i_roi_pixel_mask.h @@ -0,0 +1,50 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_I_ROI_PIXEL_MASK_H +#define METAVISION_HAL_I_ROI_PIXEL_MASK_H + +#include +#include +#include + +#include "metavision/hal/facilities/i_registrable_facility.h" + +namespace Metavision { + +/// @brief Interface facility for ROI (Region Of Interest) pixel mask +class I_RoiPixelMask : public I_RegistrableFacility { +public: + /// @brief Set individual pixel ROI mask + /// The pixel coordinates are stored in the driver and will be sent to the sensor when apply_pixels function is + /// called. + /// @param column Pixel x coordinate + /// @param row Pixel y coordinate + /// @param enable Pixel will be masked when true + /// @return true on success + virtual bool set_pixel(const unsigned int &column, const unsigned int &row, const bool &enable) = 0; + + /// @brief Apply pixels configuration to sensor + /// Pixels selected to be masked with the set_pixel function are applied to the sensor hardware. + virtual void apply_pixels() = 0; + + /// @brief Reset pixels configuration applied on the sensor + /// All previous pixels masked on the sensor will be enabled back. Pixels configuration in the driver is cleared. + virtual void reset_pixels() = 0; + + /// @brief Get list of pixels selected for masking + /// @return list of x, y coordinates + virtual std::vector> get_pixels() const = 0; +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_I_ROI_PIXEL_MASK_H diff --git a/hal/cpp/include/metavision/hal/utils/hal_error_code.h b/hal/cpp/include/metavision/hal/utils/hal_error_code.h index 9ebdfafff..3e14ece07 100644 --- a/hal/cpp/include/metavision/hal/utils/hal_error_code.h +++ b/hal/cpp/include/metavision/hal/utils/hal_error_code.h @@ -50,7 +50,8 @@ enum Enum : HalErrorCodeType { OperationNotImplemented = CameraError | 0x04000, /// Operation reached maximum retries limit - MaximumRetriesExeeded = CameraError | 0x05000, + MaximumRetriesExeeded = CameraError | 0x05000, + MaximumRetriesExceeded = CameraError | 0x05000, }; } diff --git a/hal/cpp/samples/CMakeLists.txt b/hal/cpp/samples/CMakeLists.txt index bc00e69dd..5939b709f 100644 --- a/hal/cpp/samples/CMakeLists.txt +++ b/hal/cpp/samples/CMakeLists.txt @@ -12,4 +12,5 @@ add_subdirectory(metavision_hal_ls) add_subdirectory(metavision_hal_raw_cutter) add_subdirectory(metavision_hal_seek) add_subdirectory(metavision_hal_sync) -add_subdirectory(metavision_hal_sample_plugin) \ No newline at end of file +add_subdirectory(metavision_hal_sample_plugin) +add_subdirectory(metavision_platform_info) \ No newline at end of file diff --git a/hal/cpp/samples/metavision_hal_ls/CMakeLists.txt b/hal/cpp/samples/metavision_hal_ls/CMakeLists.txt index 2149a8dd1..92d27a43b 100644 --- a/hal/cpp/samples/metavision_hal_ls/CMakeLists.txt +++ b/hal/cpp/samples/metavision_hal_ls/CMakeLists.txt @@ -11,12 +11,12 @@ add_executable(metavision_hal_ls metavision_hal_ls.cpp) target_link_libraries(metavision_hal_ls PRIVATE metavision_hal_discovery Boost::program_options) install(FILES metavision_hal_ls.cpp - DESTINATION share/metavision/hal/samples/metavision_hal_ls + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_ls COMPONENT metavision-hal-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/hal/samples/metavision_hal_ls + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_ls COMPONENT metavision-hal-samples ) \ No newline at end of file diff --git a/hal/cpp/samples/metavision_hal_raw_cutter/CMakeLists.txt b/hal/cpp/samples/metavision_hal_raw_cutter/CMakeLists.txt index 241be6035..09c98e7d1 100644 --- a/hal/cpp/samples/metavision_hal_raw_cutter/CMakeLists.txt +++ b/hal/cpp/samples/metavision_hal_raw_cutter/CMakeLists.txt @@ -11,13 +11,13 @@ add_executable(metavision_hal_raw_cutter metavision_hal_raw_cutter.cpp) target_link_libraries(metavision_hal_raw_cutter PRIVATE metavision_hal_discovery Boost::program_options) install(FILES metavision_hal_raw_cutter.cpp - DESTINATION share/metavision/hal/apps/metavision_hal_raw_cutter + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_raw_cutter COMPONENT metavision-hal-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/hal/apps/metavision_hal_raw_cutter + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_raw_cutter COMPONENT metavision-hal-samples ) diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/CMakeLists.txt b/hal/cpp/samples/metavision_hal_sample_plugin/CMakeLists.txt index bb7a44dae..6f022b54f 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/CMakeLists.txt +++ b/hal/cpp/samples/metavision_hal_sample_plugin/CMakeLists.txt @@ -60,12 +60,12 @@ endif (BUILD_TESTING) # Install sample install(DIRECTORY include src - DESTINATION share/metavision/hal/samples/metavision_hal_sample_plugin + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_sample_plugin COMPONENT metavision-hal-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/hal/samples/metavision_hal_sample_plugin + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_sample_plugin COMPONENT metavision-hal-samples ) diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/test/CMakeLists.txt b/hal/cpp/samples/metavision_hal_sample_plugin/test/CMakeLists.txt index a70d5ff5e..8ecd891a6 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/test/CMakeLists.txt +++ b/hal/cpp/samples/metavision_hal_sample_plugin/test/CMakeLists.txt @@ -7,7 +7,7 @@ # 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. -lfs_download(datasets/openeb/sample_plugin_recording.raw) +lfs_download(datasets/openeb/sample_plugin_recording.raw VALIDATION) add_executable(gtest_metavision_hal_sample_plugin ${CMAKE_CURRENT_SOURCE_DIR}/hal_sample_plugin_gtest.cpp diff --git a/hal/cpp/samples/metavision_hal_seek/CMakeLists.txt b/hal/cpp/samples/metavision_hal_seek/CMakeLists.txt index 033a83ad8..cacd62434 100644 --- a/hal/cpp/samples/metavision_hal_seek/CMakeLists.txt +++ b/hal/cpp/samples/metavision_hal_seek/CMakeLists.txt @@ -14,12 +14,12 @@ find_package(Threads REQUIRED) target_link_libraries(metavision_hal_seek PRIVATE metavision_hal_discovery Boost::program_options ${OpenCV_LIBS} Threads::Threads) install(FILES metavision_hal_seek.cpp - DESTINATION share/metavision/hal/samples/metavision_hal_seek + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_seek COMPONENT metavision-hal-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/hal/samples/metavision_hal_seek + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_seek COMPONENT metavision-hal-samples ) diff --git a/hal/cpp/samples/metavision_hal_showcase/CMakeLists.txt b/hal/cpp/samples/metavision_hal_showcase/CMakeLists.txt index 59f03e3f5..b63bcb8be 100644 --- a/hal/cpp/samples/metavision_hal_showcase/CMakeLists.txt +++ b/hal/cpp/samples/metavision_hal_showcase/CMakeLists.txt @@ -14,12 +14,12 @@ find_package(Threads REQUIRED) target_link_libraries(metavision_hal_showcase PRIVATE metavision_hal_discovery Boost::program_options ${OpenCV_LIBS} Threads::Threads) install(FILES metavision_hal_showcase.cpp - DESTINATION share/metavision/hal/samples/metavision_hal_showcase + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_showcase COMPONENT metavision-hal-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/hal/samples/metavision_hal_showcase + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_showcase COMPONENT metavision-hal-samples ) diff --git a/hal/cpp/samples/metavision_hal_showcase/metavision_hal_showcase.cpp b/hal/cpp/samples/metavision_hal_showcase/metavision_hal_showcase.cpp index 660e73b59..ebd8e6f74 100644 --- a/hal/cpp/samples/metavision_hal_showcase/metavision_hal_showcase.cpp +++ b/hal/cpp/samples/metavision_hal_showcase/metavision_hal_showcase.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -252,11 +252,11 @@ int main(int argc, char *argv[]) { } /// [biases] - Metavision::I_EventRateNoiseFilterModule *i_event_rate_noise_filter_module = - device->get_facility(); - if (i_event_rate_noise_filter_module) { - std::cout << "Event rate noise filter: streaming from " - << i_event_rate_noise_filter_module->get_event_rate_threshold() << "Kev/s" << std::endl; + Metavision::I_EventRateActivityFilterModule *i_event_rate_activity_filter_module = + device->get_facility(); + if (i_event_rate_activity_filter_module) { + std::cout << "Event rate activity filter: streaming from " + << i_event_rate_activity_filter_module->get_event_rate_threshold() << " Kev/s" << std::endl; } auto tokenize = [](std::string str, std::string separator) { diff --git a/hal/cpp/samples/metavision_hal_sync/CMakeLists.txt b/hal/cpp/samples/metavision_hal_sync/CMakeLists.txt index 89d96a937..c8667ff4d 100644 --- a/hal/cpp/samples/metavision_hal_sync/CMakeLists.txt +++ b/hal/cpp/samples/metavision_hal_sync/CMakeLists.txt @@ -14,12 +14,12 @@ find_package(Threads REQUIRED) target_link_libraries(metavision_hal_sync PRIVATE metavision_hal_discovery Boost::program_options ${OpenCV_LIBS} Threads::Threads) install(FILES metavision_hal_sync.cpp - DESTINATION share/metavision/hal/samples/metavision_hal_sync + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_sync COMPONENT metavision-hal-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/hal/samples/metavision_hal_sync + DESTINATION share/metavision/hal/cpp_samples/metavision_hal_sync COMPONENT metavision-hal-samples ) diff --git a/hal/cpp/samples/metavision_hal_sync/metavision_hal_sync.cpp b/hal/cpp/samples/metavision_hal_sync/metavision_hal_sync.cpp index e16fa98a4..e6e1cc47a 100644 --- a/hal/cpp/samples/metavision_hal_sync/metavision_hal_sync.cpp +++ b/hal/cpp/samples/metavision_hal_sync/metavision_hal_sync.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/hal/cpp/apps/metavision_platform_info/CMakeLists.txt b/hal/cpp/samples/metavision_platform_info/CMakeLists.txt similarity index 87% rename from hal/cpp/apps/metavision_platform_info/CMakeLists.txt rename to hal/cpp/samples/metavision_platform_info/CMakeLists.txt index bb2f1c21e..d774f3b5d 100644 --- a/hal/cpp/apps/metavision_platform_info/CMakeLists.txt +++ b/hal/cpp/samples/metavision_platform_info/CMakeLists.txt @@ -16,12 +16,12 @@ install(TARGETS metavision_platform_info ) install(FILES metavision_platform_info.cpp - DESTINATION share/metavision/hal/apps/metavision_platform_info + DESTINATION share/metavision/hal/cpp_samples/metavision_platform_info COMPONENT metavision-hal-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/hal/apps/metavision_platform_info + DESTINATION share/metavision/hal/cpp_samples/metavision_platform_info COMPONENT metavision-hal-samples ) \ No newline at end of file diff --git a/hal/cpp/apps/metavision_platform_info/CMakeLists.txt.install b/hal/cpp/samples/metavision_platform_info/CMakeLists.txt.install similarity index 100% rename from hal/cpp/apps/metavision_platform_info/CMakeLists.txt.install rename to hal/cpp/samples/metavision_platform_info/CMakeLists.txt.install diff --git a/hal/cpp/apps/metavision_platform_info/metavision_platform_info.cpp b/hal/cpp/samples/metavision_platform_info/metavision_platform_info.cpp similarity index 100% rename from hal/cpp/apps/metavision_platform_info/metavision_platform_info.cpp rename to hal/cpp/samples/metavision_platform_info/metavision_platform_info.cpp diff --git a/hal/cpp/test/dummy_test_plugin_facilities_builder.cpp b/hal/cpp/test/dummy_test_plugin_facilities_builder.cpp index 393555885..85778c194 100644 --- a/hal/cpp/test/dummy_test_plugin_facilities_builder.cpp +++ b/hal/cpp/test/dummy_test_plugin_facilities_builder.cpp @@ -20,7 +20,7 @@ #include "metavision/hal/facilities/i_digital_crop.h" #include "metavision/hal/facilities/i_digital_event_mask.h" #include "metavision/hal/facilities/i_erc_module.h" -#include "metavision/hal/facilities/i_event_rate_noise_filter_module.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" #include "metavision/hal/facilities/i_event_trail_filter_module.h" #include "metavision/hal/facilities/i_events_stream.h" #include "metavision/hal/facilities/i_hw_identification.h" @@ -43,21 +43,27 @@ using namespace Metavision; -// TODO MV-1443 : move this class in the unnamed namespace below, the Test namespace is only here -// to enable the dynamic_cast used in the camera gtest (which we won't need as soon as we use -// public HAL API to get access to some fields) -namespace Test { +namespace { + struct DummyROI : public I_ROI { bool enable(bool state) override { enabled_ = state; return true; } + bool is_enabled() const override { + return enabled_; + } + bool set_mode(const Mode &mode) override { mode_ = mode; return true; } + Mode get_mode() const override { + return mode_; + } + size_t get_max_supported_windows_count() const override { return 5; } @@ -73,14 +79,15 @@ struct DummyROI : public I_ROI { return true; } + std::vector get_windows() const override { + return windows_; + } + bool enabled_{false}; Mode mode_; std::vector windows_; std::vector rows_, cols_; }; -} // namespace Test - -namespace { struct DummyDataTransfer : public DataTransfer { DummyDataTransfer() : DataTransfer(1) {} @@ -630,7 +637,7 @@ struct DummyErcModule : public I_ErcModule { uint32_t cd_event_count_ = 1000; }; -struct DummyNFLModule : public I_EventRateNoiseFilterModule { +struct DummyNFLModule : public I_EventRateActivityFilterModule { public: virtual bool enable(bool b) override { enabled_ = b; @@ -650,9 +657,31 @@ struct DummyNFLModule : public I_EventRateNoiseFilterModule { return threshold_; } + virtual thresholds is_thresholds_supported() const override { + return {1, 1, 1, 1}; + } + + virtual bool set_thresholds(const thresholds &thresholds_ev_s) override { + thresholds_ = thresholds_ev_s; + return true; + } + + virtual thresholds get_thresholds() const override { + return thresholds_; + } + + virtual thresholds get_min_supported_thresholds() const override { + return {0, 0, 0, 0}; + } + + virtual thresholds get_max_supported_thresholds() const override { + return {200000, 200000, 1600000000, 1600000000}; + } + private: - bool enabled_ = false; - uint32_t threshold_ = 1000; + bool enabled_ = false; + uint32_t threshold_ = 1000; + thresholds thresholds_ = {300000, 280000, 800000000, 800000000}; }; struct DummyCameraDiscovery : public CameraDiscovery { @@ -675,7 +704,7 @@ struct DummyCameraDiscovery : public CameraDiscovery { device_builder.add_facility(std::make_unique()); device_builder.add_facility(std::make_unique()); device_builder.add_facility(std::make_unique()); - device_builder.add_facility(std::make_unique()); + device_builder.add_facility(std::make_unique()); // To make dummy plugin usable in Metavision::Camera device_builder.add_facility(std::make_unique(device_builder.get_plugin_software_info())); device_builder.add_facility(std::make_unique(640, 480)); diff --git a/hal/cpp/test/dummy_test_plugin_gtest.cpp b/hal/cpp/test/dummy_test_plugin_gtest.cpp index 15e249d84..b7d863568 100644 --- a/hal/cpp/test/dummy_test_plugin_gtest.cpp +++ b/hal/cpp/test/dummy_test_plugin_gtest.cpp @@ -18,7 +18,7 @@ #include "metavision/hal/facilities/i_antiflicker_module.h" #include "metavision/hal/facilities/i_camera_synchronization.h" #include "metavision/hal/facilities/i_erc_module.h" -#include "metavision/hal/facilities/i_event_rate_noise_filter_module.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" #include "metavision/hal/facilities/i_events_stream_decoder.h" #include "metavision/hal/facilities/i_digital_crop.h" #include "metavision/hal/facilities/i_digital_event_mask.h" @@ -59,7 +59,7 @@ TEST_F(DummyTestPluginTest, should_have_facilities) { EXPECT_THAT(dummy_device->get_facility(), NotNull()); EXPECT_THAT(dummy_device->get_facility(), NotNull()); EXPECT_THAT(dummy_device->get_facility(), NotNull()); - EXPECT_THAT(dummy_device->get_facility(), NotNull()); + EXPECT_THAT(dummy_device->get_facility(), NotNull()); EXPECT_THAT(dummy_device->get_facility(), NotNull()); EXPECT_THAT(dummy_device->get_facility(), NotNull()); EXPECT_THAT(dummy_device->get_facility(), NotNull()); diff --git a/hal/python/bindings/CMakeLists.txt b/hal/python/bindings/CMakeLists.txt index 5bba6c667..e22a2950c 100644 --- a/hal/python/bindings/CMakeLists.txt +++ b/hal/python/bindings/CMakeLists.txt @@ -18,7 +18,7 @@ set(hal_python_srcs ${CMAKE_CURRENT_SOURCE_DIR}/i_event_cd_decoder_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_event_ext_trigger_decoder_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_event_frame_decoder_python.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/i_event_rate_noise_filter_module_python.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/i_event_rate_activity_filter_module_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_events_stream_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_events_stream_decoder_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_geometry_python.cpp @@ -27,6 +27,7 @@ set(hal_python_srcs ${CMAKE_CURRENT_SOURCE_DIR}/i_hw_register_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_ll_biases_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_monitoring_python.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/i_roi_pixel_mask_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_event_trail_filter_module_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_plugin_software_info_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_roi_python.cpp @@ -38,20 +39,20 @@ set(hal_python_srcs ${CMAKE_CURRENT_SOURCE_DIR}/raw_file_header_python.cpp ) -if (GENERATE_DOC_PYTHON_BINDINGS) - set (hal_python_dependencies metavision_hal_python_doc_from_cpp) - set (hal_python_include_directories ${GENERATE_PYTHON_BINDINGS_DOC_DIRECTORY}) - set (hal_python_compile_definitions GENERATE_DOC_PYTHON_BINDINGS_USING_CPP_COMMENTS) +if(GENERATE_DOC_PYTHON_BINDINGS) + set(hal_python_dependencies metavision_hal_python_doc_from_cpp) + set(hal_python_include_directories ${GENERATE_PYTHON_BINDINGS_DOC_DIRECTORY}) + set(hal_python_compile_definitions GENERATE_DOC_PYTHON_BINDINGS_USING_CPP_COMMENTS) endif() add_hal_python_bindings( SOURCES ${hal_python_srcs} LINK_LIBRARIES - PUBLIC - metavision_hal - metavision_hal_discovery - PRIVATE - MetavisionUtils::pybind + PUBLIC + metavision_hal + metavision_hal_discovery + PRIVATE + MetavisionUtils::pybind INCLUDE_DIRECTORIES PRIVATE ${hal_python_include_directories} COMPILE_DEFINITIONS PRIVATE ${hal_python_compile_definitions} DEPENDENCIES ${hal_python_dependencies} diff --git a/hal/python/bindings/i_event_rate_activity_filter_module_python.cpp b/hal/python/bindings/i_event_rate_activity_filter_module_python.cpp new file mode 100644 index 000000000..e33e4918b --- /dev/null +++ b/hal/python/bindings/i_event_rate_activity_filter_module_python.cpp @@ -0,0 +1,57 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#include "hal_python_binder.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" +#include "pb_doc_hal.h" + +namespace Metavision { + +static DeviceFacilityGetter getter("get_i_event_rate"); + +static HALFacilityPythonBinder bind( + [](auto &module, auto &class_binding) { + class_binding + .def("enable", &I_EventRateActivityFilterModule::enable, py::arg("enable_filter"), + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::enable"]) + .def("is_enabled", &I_EventRateActivityFilterModule::is_enabled, + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::is_enabled"]) + .def("set_event_rate_threshold", &I_EventRateActivityFilterModule::set_event_rate_threshold, + py::arg("threshold_Kev_s"), + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::set_event_rate_threshold"]) + .def("get_event_rate_threshold", &I_EventRateActivityFilterModule::get_event_rate_threshold, + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::get_event_rate_threshold"]) + + .def("get_thresholds", &I_EventRateActivityFilterModule::get_thresholds, + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::get_thresholds"]) + + .def("set_thresholds", &I_EventRateActivityFilterModule::set_thresholds, py::arg("threshold_ev_s"), + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::set_thresholds"]) + + .def("is_thresholds_supported", &I_EventRateActivityFilterModule::is_thresholds_supported, + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::is_thresholds_supported"]) + + .def("get_min_supported_thresholds", &I_EventRateActivityFilterModule::get_min_supported_thresholds, + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::get_min_supported_thresholds"]) + + .def("get_max_supported_thresholds", &I_EventRateActivityFilterModule::get_max_supported_thresholds, + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::get_max_supported_thresholds"]); + + py::class_( + class_binding, "thresholds", pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::thresholds"]) + .def_readwrite("lower_bound_start", &I_EventRateActivityFilterModule::thresholds::lower_bound_start) + .def_readwrite("lower_bound_stop", &I_EventRateActivityFilterModule::thresholds::lower_bound_stop) + .def_readwrite("upper_bound_start", &I_EventRateActivityFilterModule::thresholds::upper_bound_start) + .def_readwrite("upper_bound_stop", &I_EventRateActivityFilterModule::thresholds::upper_bound_stop); + }, + "I_EventRateActivityFilterModule", pybind_doc_hal["Metavision::I_EventRateActivityFilterModule"]); + +} // namespace Metavision diff --git a/hal/python/bindings/i_event_rate_noise_filter_module_python.cpp b/hal/python/bindings/i_roi_pixel_mask_python.cpp similarity index 55% rename from hal/python/bindings/i_event_rate_noise_filter_module_python.cpp rename to hal/python/bindings/i_roi_pixel_mask_python.cpp index e4bf76922..88b24c897 100644 --- a/hal/python/bindings/i_event_rate_noise_filter_module_python.cpp +++ b/hal/python/bindings/i_roi_pixel_mask_python.cpp @@ -10,26 +10,19 @@ **********************************************************************************************************************/ #include "hal_python_binder.h" -#include "metavision/hal/facilities/i_event_rate_noise_filter_module.h" +#include "metavision/hal/facilities/i_roi_pixel_mask.h" #include "pb_doc_hal.h" namespace Metavision { -static DeviceFacilityGetter getter("get_i_event_rate"); +static DeviceFacilityGetter getter("get_i_roi_pixel_mask"); -static HALFacilityPythonBinder bind( +static HALFacilityPythonBinder bind_digital_crop( [](auto &module, auto &class_binding) { class_binding - .def("enable", &I_EventRateNoiseFilterModule::enable, py::arg("enable_filter"), - pybind_doc_hal["Metavision::I_EventRateNoiseFilterModule::enable"]) - .def("is_enabled", &I_EventRateNoiseFilterModule::is_enabled, - pybind_doc_hal["Metavision::I_EventRateNoiseFilterModule::is_enabled"]) - .def("set_event_rate_threshold", &I_EventRateNoiseFilterModule::set_event_rate_threshold, - py::arg("threshold_Kev_s"), - pybind_doc_hal["Metavision::I_EventRateNoiseFilterModule::set_event_rate_threshold"]) - .def("get_event_rate_threshold", &I_EventRateNoiseFilterModule::get_event_rate_threshold, - pybind_doc_hal["Metavision::I_EventRateNoiseFilterModule::get_event_rate_threshold"]); + .def("set_pixel", &I_RoiPixelMask::set_pixel, pybind_doc_hal["Metavision::I_RoiPixelMask::set_pixel"]) + .def("apply_pixels", &I_RoiPixelMask::apply_pixels, + pybind_doc_hal["Metavision::I_RoiPixelMask::apply_pixels"]); }, - "I_EventRateNoiseFilterModule", pybind_doc_hal["Metavision::I_EventRateNoiseFilterModule"]); - + "I_RoiPixelMask", pybind_doc_hal["Metavision::I_RoiPixelMask"]); } // namespace Metavision diff --git a/hal_psee_plugins/CMakeLists.txt b/hal_psee_plugins/CMakeLists.txt index fa5f475c1..c8da15f0b 100644 --- a/hal_psee_plugins/CMakeLists.txt +++ b/hal_psee_plugins/CMakeLists.txt @@ -15,6 +15,10 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/src/devices/sensorlib") set(HAL_SENSORLIB_SUPPORT TRUE) endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/src/devices/sensorlib") +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/src/devices/evk3d") + set(HAL_EVK3D_SUPPORT TRUE) +endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/src/devices/evk3d") + # Add libraries (plugins) set(biasgen_calib_files_dir "${GENERATE_FILES_DIRECTORY}/biasgen_calib") set(metavision_hal_psee_plugins_include_dir "${CMAKE_CURRENT_SOURCE_DIR}/include") @@ -39,9 +43,7 @@ if (BUILD_TESTING) endif (BUILD_TESTING) # Project Raven -if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/raven") - add_subdirectory(raven) -endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/raven") +add_subdirectory_if_exists(raven) add_cpack_component(PUBLIC metavision-hal-prophesee-hw-layer-lib metavision-hal-prophesee-hw-layer-dev) add_cpack_component(PUBLIC metavision-hal-prophesee-plugins) diff --git a/hal_psee_plugins/include/devices/genx320/genx320_cx3_tz_device.h b/hal_psee_plugins/include/devices/genx320/genx320_cx3_tz_device.h index f6b78c211..e11937015 100644 --- a/hal_psee_plugins/include/devices/genx320/genx320_cx3_tz_device.h +++ b/hal_psee_plugins/include/devices/genx320/genx320_cx3_tz_device.h @@ -18,7 +18,11 @@ namespace Metavision { -class TzCx3GenX320 : public TzIssdDevice, public TzMainDevice, public TemperatureProvider { +class TzCx3GenX320 : public TzIssdDevice, + public TzMainDevice, + public TemperatureProvider, + public IlluminationProvider, + public PixelDeadTimeProvider { public: TzCx3GenX320(std::shared_ptr cmd, uint32_t dev_id, std::shared_ptr parent); virtual ~TzCx3GenX320(); @@ -38,6 +42,8 @@ class TzCx3GenX320 : public TzIssdDevice, public TzMainDevice, public Temperatur } long long get_sensor_id(); virtual int get_temperature(); + virtual int get_illumination(); + virtual int get_pixel_dead_time(); protected: virtual void spawn_facilities(DeviceBuilder &device_builder, const DeviceConfig &device_config); @@ -45,6 +51,10 @@ class TzCx3GenX320 : public TzIssdDevice, public TzMainDevice, public Temperatur private: I_CameraSynchronization::SyncMode sync_mode_; void time_base_config(bool external, bool master); + void iph_mirror_control(bool enable); + void lifo_control(bool enable, bool cnt_enable); + std::vector lifo_acquisition(int expected_wait_time); + void temperature_init(); }; } // namespace Metavision diff --git a/hal_psee_plugins/include/devices/utils/device_system_id.h b/hal_psee_plugins/include/devices/utils/device_system_id.h index 2eef317b8..c556f9ea8 100644 --- a/hal_psee_plugins/include/devices/utils/device_system_id.h +++ b/hal_psee_plugins/include/devices/utils/device_system_id.h @@ -62,6 +62,7 @@ enum SystemId : long { SYSTEM_EVK2_SAPHIR = 0x37, SYSTEM_RDK2_IMX636 = 0x3A, SYSTEM_EVK3_GENX320 = 0x40, + SYSTEM_EVK3D_SL = 0x41, SYSTEM_FX3_UNKNOWN = static_cast(0xFFFFFFF0), SYSTEM_INVALID_NO_FPGA = static_cast(0xFFFFFFFF) }; @@ -123,6 +124,7 @@ static const std::map SYSTEMS_NAME = { { SYSTEM_EVK3_IMX647, "IMX647 VGA EVK3"}, { SYSTEM_EVK3_GENX320, "GenX320 ES EVK3"}, { SYSTEM_RDK2_IMX636, "IMX636 HD RDK2"}, + { SYSTEM_EVK3D_SL, "EVK3D Structured Light"}, { SYSTEM_FX3_UNKNOWN, "FX3 EMPTY DEVICE"} }; // clang-format on @@ -166,6 +168,7 @@ static const std::map SYSTEMS_DATA_TRANSFE { SYSTEM_EVK3_IMX647, DataTransferProtocol::USB}, { SYSTEM_EVK3_GENX320, DataTransferProtocol::USB}, { SYSTEM_RDK2_IMX636, DataTransferProtocol::USB}, + { SYSTEM_EVK3D_SL, DataTransferProtocol::USB}, { SYSTEM_FX3_UNKNOWN, DataTransferProtocol::USB} }; // clang-format on @@ -221,6 +224,7 @@ inline bool systemid2version(long system_id, uint16_t &major_version, uint16_t & break; case SystemId::SYSTEM_EVK2_GEN41: case SystemId::SYSTEM_EVK3_GEN41: + case SystemId::SYSTEM_EVK3D_SL: major_version = 4; minor_version = 1; break; diff --git a/hal_psee_plugins/lib/CMakeLists.txt b/hal_psee_plugins/lib/CMakeLists.txt index bb0988d95..3df95f506 100644 --- a/hal_psee_plugins/lib/CMakeLists.txt +++ b/hal_psee_plugins/lib/CMakeLists.txt @@ -169,6 +169,13 @@ if(HAL_SENSORLIB_SUPPORT) ) endif(HAL_SENSORLIB_SUPPORT) +if(HAL_EVK3D_SUPPORT) + list(APPEND lib_camera_obj_list + metavision_hal_evk3d_system_obj + ) +endif(HAL_EVK3D_SUPPORT) + + set(lib_obj_list ${lib_common_obj_list} ${lib_camera_obj_list}) foreach(lib_obj ${lib_obj_list}) diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_event_rate_noise_filter_module.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_event_rate_noise_filter_module.h index c67d1aefc..36656015f 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_event_rate_noise_filter_module.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_event_rate_noise_filter_module.h @@ -14,20 +14,29 @@ #include -#include "metavision/hal/facilities/i_event_rate_noise_filter_module.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" namespace Metavision { class I_HW_Register; -class Gen31_EventRateNoiseFilterModule : public I_EventRateNoiseFilterModule { +class Gen31_EventRateNoiseFilterModule : public I_EventRateActivityFilterModule { public: + using NflThresholds = I_EventRateActivityFilterModule::thresholds; + Gen31_EventRateNoiseFilterModule(const std::shared_ptr &i_hw_register, const std::string &prefix); - virtual bool enable(bool enable_filter) override; - virtual bool is_enabled() const override; - virtual bool set_event_rate_threshold(uint32_t threshold_Kev_s) override; - virtual uint32_t get_event_rate_threshold() const override; + bool enable(bool enable_filter) override; + bool is_enabled() const override; + bool set_event_rate_threshold(uint32_t threshold_Kev_s) override; + uint32_t get_event_rate_threshold() const override; + + NflThresholds is_thresholds_supported() const override; + bool set_thresholds(const NflThresholds &thresholds_ev_s) override; + NflThresholds get_thresholds() const override; + + NflThresholds get_min_supported_thresholds() const override; + NflThresholds get_max_supported_thresholds() const override; static constexpr uint32_t min_time_window_us_ = 1; static constexpr uint32_t max_time_window_us_ = 1023; diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_roi_command.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_roi_command.h index 4f7efbef7..dfd2fcf94 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_roi_command.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_roi_command.h @@ -27,6 +27,7 @@ class Gen31ROICommand : public PseeROI { Gen31ROICommand(int width, int height, const std::shared_ptr ®map, const std::string &prefix); virtual bool enable(bool state) override; + virtual bool is_enabled() const override; virtual void write_ROI(const std::vector &vroiparams) override; private: @@ -36,6 +37,7 @@ class Gen31ROICommand : public PseeROI { std::shared_ptr register_map_; const std::string prefix_; std::vector roi_save_; + bool enabled_ = false; }; } // namespace Metavision diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen41/gen41_roi_command.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen41/gen41_roi_command.h index c21f331f4..12f1bae1f 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen41/gen41_roi_command.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen41/gen41_roi_command.h @@ -26,17 +26,19 @@ class Gen41ROICommand : public PseeROI { const std::string &sensor_prefix); virtual bool set_mode(const Mode &mode) override; + virtual Mode get_mode() const override; virtual bool enable(bool state) override; + virtual bool is_enabled() const override; virtual void write_ROI(const std::vector &vroiparams) override; private: void reset_to_full_roi(); -private: std::shared_ptr register_map_; std::vector roi_save_; std::string sensor_prefix_; I_ROI::Mode mode_; + bool enabled_ = false; }; } // namespace Metavision diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_dem_driver.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_dem_driver.h new file mode 100644 index 000000000..eed150075 --- /dev/null +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_dem_driver.h @@ -0,0 +1,68 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_GENX320_DEM_DRIVER_H +#define METAVISION_HAL_GENX320_DEM_DRIVER_H + +#include "metavision/psee_hw_layer/utils/register_map.h" +#include "metavision/hal/facilities/i_registrable_facility.h" + +namespace Metavision { + +/// @brief Digital Event Mask implementation for GenX320 +class GenX320DemDriver : public I_RegistrableFacility { + using RegAcc = RegisterMap::RegisterAccess; + +public: + struct VectorMask { + uint32_t y; + uint32_t x_group; + uint32_t vector; + }; + + class MaskSlot { + public: + MaskSlot(const RegAcc ®_ctrl, const RegAcc ®_data); + void update(bool enable); + bool is_valid(); + + bool empty_; + VectorMask vmask_; + RegAcc reg_ctrl_; + RegAcc reg_data_; + }; + + GenX320DemDriver(const std::shared_ptr ®map, const std::string &prefix); + + bool set_pixel_filter(uint32_t x, uint32_t y, bool enabled); + bool is_pixel_filtered(uint32_t x, uint32_t y); + + const std::vector &get_masks() const; + + bool set_mask(VectorMask mask, uint32_t id, bool enable); + MaskSlot get_mask(const unsigned int id) const; + + static VectorMask vectorize(uint32_t x, uint32_t y); + static std::tuple extract_coord(VectorMask vmask); + +private: + std::shared_ptr regmap_; + std::string prefix_; + std::vector mslots_; + constexpr static size_t NUM_MASK_SLOTS_ = 16; + + static int is_power_of_two(unsigned int n); + static int find_position(unsigned int n); +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_GENX320_DEM_DRIVER_H diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_dem_interface.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_dem_interface.h new file mode 100644 index 000000000..b0539566f --- /dev/null +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_dem_interface.h @@ -0,0 +1,64 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_PSEE_PLUGINS_DEVICES_GENX320_DEM_INTERFACE +#define METAVISION_HAL_PSEE_PLUGINS_DEVICES_GENX320_DEM_INTERFACE + +#include "metavision/hal/facilities/i_digital_event_mask.h" +#include "metavision/psee_hw_layer/utils/register_map.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_dem_driver.h" + +namespace Metavision { + +/// @brief Digital Event Mask implementation for GenX320 +class GenX320DemInterface : public I_DigitalEventMask { +private: + /// @brief Pixel Mask implementation for GenX320 + class GenX320PixelMask : public I_PixelMask { + public: + /// @brief Pixel Mask Constructor + GenX320PixelMask(const std::shared_ptr &driver, const unsigned int id); + + /// @brief Sets mask pixel coordinate and activation flag + /// @param x the pixel horizontal coordinate + /// @param y the pixel vertical coordinate + /// @param enable when true, the mask will prevent pixel from generating CD event + /// @return true on success + virtual bool set_mask(uint32_t x, uint32_t y, bool enabled) override; + + /// @brief Get the current mask settings + /// @return a tuple that packs the X and Y coordinates and a boolean defining if the mask is enabled + virtual std::tuple get_mask() const override; + + private: + std::shared_ptr driver_; + unsigned int id_; + }; + + constexpr static size_t NUM_MASK_REGISTERS_ = 16; + + std::vector pixel_masks_; + std::shared_ptr mask_ctrl_; + +public: + /// @brief GenX320DemInterface constructor + /// @param regmap the Register map associated with the sensor + /// @param prefix the path to the digital pixel mask registers in the regmap + GenX320DemInterface(const std::shared_ptr ®map, const std::string &prefix); + + /// @brief Get all available masks. + /// @return a list of pixel masks pointer + virtual const std::vector &get_pixel_masks() const override; +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_PSEE_PLUGINS_DEVICES_GENX320_DEM_INTERFACE diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_digital_crop.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_digital_crop.h new file mode 100644 index 000000000..3c1a03173 --- /dev/null +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_digital_crop.h @@ -0,0 +1,59 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_PSEE_PLUGINS_DEVICES_GENX320_DIGITAL_CROP_H +#define METAVISION_HAL_PSEE_PLUGINS_DEVICES_GENX320_DIGITAL_CROP_H + +#include "metavision/hal/facilities/i_digital_crop.h" +#include "metavision/psee_hw_layer/utils/register_map.h" + +namespace Metavision { + +/// @brief Digital Crop GenX320 implementation +/// All pixels outside of the cropping region will be dropped by the sensor +class GenX320DigitalCrop : public I_DigitalCrop { + RegisterMap::FieldAccess enable_; + RegisterMap::FieldAccess drop_; + RegisterMap::FieldAccess reset_orig_; + RegisterMap::FieldAccess start_x_; + RegisterMap::FieldAccess start_y_; + RegisterMap::FieldAccess end_x_; + RegisterMap::FieldAccess end_y_; + +public: + /// @brief GenX320DigitalCrop constructor + /// @param regmap the Register map for the sensor + /// @param prefix the prefix path to retrieve registers in the regmap + GenX320DigitalCrop(const std::shared_ptr ®map, const std::string &prefix); + + /// @brief Applies Digital Crop + /// @param state If true, enables Digital Crop. If false, disables it + /// @return true on success + bool enable(bool state) override; + + /// @brief Returns Digital Crop activation state + /// @return The Digital Crop state + bool is_enabled() const override; + + /// @brief Defines digital crop window region + /// @param region The region of pixels that should be cropped + /// @param reset_origin If true, the origin of the event output coordinates will shift to the Crop Window start + /// @warning When reset_origin is true, start_x must be a multiple of 32 and end_x a multiple of 31, + bool set_window_region(const Region ®ion, bool reset_origin) override; + + /// @brief Gets the digital crop window region currently defined + /// @return digital crop window region currently defined + Region get_window_region() const override; +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_PSEE_PLUGINS_DEVICES_GENX320_DIGITAL_CROP_H diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_ll_roi.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_ll_roi.h deleted file mode 100644 index e247c7757..000000000 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_ll_roi.h +++ /dev/null @@ -1,63 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_HAL_GENX320_LL_ROI_H -#define METAVISION_HAL_GENX320_LL_ROI_H - -#include -#include - -#include "metavision/hal/facilities/i_registrable_facility.h" - -namespace Metavision { - -class DeviceConfig; -class RegisterMap; - -class GenX320LowLevelRoi : public I_RegistrableFacility { -public: - class Grid { - public: - Grid(int columns, int rows); - - void set_vector(const unsigned int &vector_id, const unsigned int &row, const unsigned int &val); - unsigned int &get_vector(const unsigned int &vector_id, const unsigned int &row); - void set_pixel(const unsigned int &column, const unsigned int &row, const bool &enable); - - /// @brief Returns the grid as a string - /// @return Human readable string representation of a grid - std::string to_string() const; - - std::tuple get_size() const; - - private: - std::vector grid_; - unsigned int rows_; - unsigned int columns_; - }; - - GenX320LowLevelRoi(const DeviceConfig &config, const std::shared_ptr ®map, - const std::string &sensor_prefix); - - void reset(); - bool apply(GenX320LowLevelRoi::Grid &user_grid); - - static std::filesystem::path default_calibration_path(); - bool load_calibration_file(const std::filesystem::path &path); - -private: - std::shared_ptr register_map_; - std::string sensor_prefix_; -}; - -} // namespace Metavision - -#endif // METAVISION_HAL_GENX320_LL_ROI_H diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_driver.h similarity index 54% rename from hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl.h rename to hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_driver.h index f1c5334d6..cf5b4d7b4 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_driver.h @@ -9,42 +9,52 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_HAL_GENX320_NOISE_FILTER_H -#define METAVISION_HAL_GENX320_NOISE_FILTER_H +#ifndef METAVISION_HAL_GENX320_NFL_DRIVER_H +#define METAVISION_HAL_GENX320_NFL_DRIVER_H #include -#include "metavision/hal/facilities/i_event_rate_noise_filter_module.h" +#include "metavision/hal/facilities/i_registrable_facility.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" namespace Metavision { class RegisterMap; -class GenX320NoiseFilter : public I_EventRateNoiseFilterModule { +class GenX320NflDriver : public I_RegistrableFacility { public: - GenX320NoiseFilter(const std::shared_ptr ®ister_map); + using NflThresholds = I_EventRateActivityFilterModule::thresholds; - virtual bool enable(bool enable_filter) override; - virtual bool is_enabled() const override; - virtual bool set_event_rate_threshold(uint32_t threshold_Kev_s) override; - virtual uint32_t get_event_rate_threshold() const override; + GenX320NflDriver(const std::shared_ptr ®ister_map); - static constexpr uint32_t min_time_window_us_ = 1; - static constexpr uint32_t max_time_window_us_ = 1023; - static constexpr uint32_t min_event_rate_threshold_kev_s = 10; - static constexpr uint32_t max_event_rate_threshold_kev_s = 10000; + bool enable(bool enable_filter); + bool is_enabled() const; + + NflThresholds is_thresholds_supported() const; + bool set_thresholds(const NflThresholds &thresholds_ev_s); + NflThresholds get_thresholds() const; + + NflThresholds get_min_supported_thresholds() const; + NflThresholds get_max_supported_thresholds() const; private: + uint32_t compute_cd_threshold(uint32_t event_rate_ev_s) const; + uint32_t compute_event_rate(uint32_t threshold) const; + bool set_time_window(uint32_t window_length_us); uint32_t get_time_window() const; - mutable uint32_t current_threshold_kev_s_{0}; - static constexpr uint32_t max_pixel_event_threshold_on = 0xFFFFFFFF; - static constexpr uint32_t max_pixel_event_threshold_off = 0xFFFFFFFF; + static constexpr uint32_t min_time_window_us = 1; + static constexpr uint32_t max_time_window_us = 1024; + static constexpr uint32_t min_pixel_event_threshold_on = 0; + static constexpr uint32_t min_pixel_event_threshold_off = 0; + static constexpr uint32_t max_pixel_event_threshold_on = 0x190000; + static constexpr uint32_t max_pixel_event_threshold_off = 0x190000; + static constexpr uint32_t max_register_value = 0x1FFFFF; std::shared_ptr register_map_; }; } // namespace Metavision -#endif // METAVISION_HAL_GENX320_NOISE_FILTER_H +#endif // METAVISION_HAL_GENX320_NFL_DRIVER_H diff --git a/hal/cpp/include/metavision/hal/facilities/i_event_rate_noise_filter_module.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h similarity index 63% rename from hal/cpp/include/metavision/hal/facilities/i_event_rate_noise_filter_module.h rename to hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h index e7a61c36c..254b6650f 100644 --- a/hal/cpp/include/metavision/hal/facilities/i_event_rate_noise_filter_module.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h @@ -9,41 +9,47 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_HAL_I_EVENT_RATE_NOISE_FILTER_MODULE_H -#define METAVISION_HAL_I_EVENT_RATE_NOISE_FILTER_MODULE_H +#ifndef METAVISION_HAL_GENX320_NFL_INTERFACE_H +#define METAVISION_HAL_GENX320_NFL_INTERFACE_H -#include - -#include "metavision/hal/facilities/i_registrable_facility.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_nfl_driver.h" namespace Metavision { -/// @brief Interface for accessing the sensor level event rate based on noise filtering of a sensor. -/// -/// This sensor level noise filter is based on the event rate only. If enabled, the sensor will transfer data if and -/// only if the event rate is above a given event rate. It avoids streaming background noise information without -/// relevant activity information. -class I_EventRateNoiseFilterModule : public I_RegistrableFacility { +class GenX320NflInterface : public I_EventRateActivityFilterModule { public: + GenX320NflInterface(const std::shared_ptr &driver); + /// @brief Enables/disables the noise filter /// @param enable_filter Whether to enable the noise filtering - virtual bool enable(bool enable_filter) = 0; + bool enable(bool enable_filter); /// @brief Returns the noise filter state /// @return the noise filter state - virtual bool is_enabled() const = 0; + bool is_enabled() const; /// @brief Sets the event rate threshold. Below this threshold, no events are streamed. /// @param threshold_Kev_s Event rate threshold in Kevt/s /// @return true if the input value was correctly set (i.e. it falls in the range of acceptable values for the /// sensor) - virtual bool set_event_rate_threshold(uint32_t threshold_Kev_s) = 0; + bool set_event_rate_threshold(uint32_t threshold_Kev_s); /// @brief Gets the event rate threshold in Kevt/s below which no events are streamed /// @return Event rate threshold in Kevt/s - virtual uint32_t get_event_rate_threshold() const = 0; + uint32_t get_event_rate_threshold() const; + + I_EventRateActivityFilterModule::thresholds is_thresholds_supported() const; + bool set_thresholds(const I_EventRateActivityFilterModule::thresholds &thresholds_ev_s); + I_EventRateActivityFilterModule::thresholds get_thresholds() const; + + I_EventRateActivityFilterModule::thresholds get_min_supported_thresholds() const; + I_EventRateActivityFilterModule::thresholds get_max_supported_thresholds() const; + +private: + std::shared_ptr driver_; }; } // namespace Metavision -#endif // METAVISION_HAL_I_EVENT_RATE_NOISE_FILTER_MODULE_H +#endif // METAVISION_HAL_GENX320_NFL_INTERFACE_H diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_driver.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_driver.h new file mode 100644 index 000000000..6318fd890 --- /dev/null +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_driver.h @@ -0,0 +1,160 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_GENX320_ROI_DRIVER_H +#define METAVISION_HAL_GENX320_ROI_DRIVER_H + +#include +#include +#include "metavision/psee_hw_layer/utils/register_map.h" +#include "metavision/hal/utils/device_config.h" +#include "metavision/hal/facilities/i_roi.h" + +#include "metavision/hal/facilities/i_registrable_facility.h" + +namespace Metavision { + +class GenX320RoiDriver : public I_RegistrableFacility { +public: + GenX320RoiDriver(int width, int height, const std::shared_ptr ®map, + const std::string &sensor_prefix, const DeviceConfig &config); + + class Grid { + public: + Grid(int columns, int rows); + + void clear(); + void set_vector(const unsigned int &vector_id, const unsigned int &row, const unsigned int &val); + unsigned int &get_vector(const unsigned int &vector_id, const unsigned int &row); + void set_pixel(const unsigned int &column, const unsigned int &row, const bool &enable); + + /// @brief Returns the grid as a string + /// @return Human readable string representation of a grid + std::string to_string() const; + + std::tuple get_size() const; + + private: + std::vector grid_; + unsigned int rows_; + unsigned int columns_; + }; + + /// @brief ROI controller driver mode + /// + /// MASTER : Region of interest controlled by ROI Master state machine + /// LATCH : Region of interest directly controlled by register access to latches + enum class DriverMode { MASTER, LATCH }; + + /// @brief Set ROI controller mode + /// @param driver_mode driver mode to set (MASTER or LATCH) + /// @return true on success + bool set_driver_mode(const DriverMode &driver_mode); + + static std::filesystem::path default_calibration_path(); + bool load_calibration_file(const std::filesystem::path &path); + + /// @brief Returns the default device width + /// + /// This values is obtained from the default Device passed in the constructor of the class. + int device_width() const; + + /// @brief Returns the default device height + /// + /// This values is obtained from the default Device passed in the constructor of the class. + int device_height() const; + + /// @brief Sets the window mode + /// @param mode window mode to set (ROI or RONI) + /// @return true on success + bool set_roi_mode(const I_ROI::Mode &mode); + + /// @brief Gets the ROI mode + /// @param mode ROI mode set (ROI or RONI) + /// @return ROI mode + I_ROI::Mode get_roi_mode() const; + + /// @brief Gets the maximum number of windows + /// @return the maximum number of windows that can be set via @ref set_windows + unsigned int get_max_windows_count() const; + + /// @brief Sets multiple ROIs Windows + /// + /// Configure windows registers of ROI master block + /// + /// @param windows A vector of windows to set + /// @return true on success + /// @throw an exception if the size of the vector is higher than the maximum supported number + /// of windows (see @ref get_max_supported_windows_count) + bool set_windows(const std::vector &windows); + + /// @brief Sets multiple ROIs from row and column binary maps + /// + /// The binary maps (std::vector) arguments must have the sensor's dimension + /// Configure Grid underlying attribute with lines + /// + /// @param cols Vector of boolean of size sensor's width representing the binary map of the columns to + /// enable + /// @param rows Vector of boolean of size sensor's height representing the binary map of the rows to + /// enable + /// @return true if input have the correct dimension and the ROI is set correctly, false otherwise + /// @warning For a pixel to be enabled, it must be enabled on both its row and column + bool set_lines(const std::vector &cols, const std::vector &rows); + + bool set_pixel(const unsigned int &column, const unsigned int &row, const bool &enable); + + /// @brief Sets Grid ROI from user Grid configuration + /// + /// Configure Grid underlying attribute with user Grid object + /// + /// @param user_grid Grid + /// @return true if input have the correct dimension and the ROI is set correctly, false otherwise + bool set_grid(Grid &user_grid); + + /// @brief Apply configured ROI Windows to sensor + /// @param window_count + void apply_windows(unsigned int window_count); + + /// @brief Apply configured Grid config to sensor + void apply_grid(); + + /// @brief Apply ROI configuration based on driver mode + /// @param state If true, enables ROI. If false, reset to full ROI + /// @warning At least one ROI should have been set before calling this function + /// @return true on success + bool enable(bool state); + + void reset_to_full_roi(); + + std::vector get_windows() const; + void print_windows_config(); + + Grid get_grid() const; + void print_grid_config(); + +private: + int device_height_{0}; + int device_width_{0}; + + std::shared_ptr register_map_; + std::string sensor_prefix_; + + DriverMode driver_mode_; + I_ROI::Mode mode_; + + Grid grid_; + I_ROI::Window main_window_; + unsigned int roi_window_cnt_; +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_GENX320_ROI_DRIVER_H diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_interface.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_interface.h new file mode 100644 index 000000000..653531f31 --- /dev/null +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_interface.h @@ -0,0 +1,81 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_GENX320_ROI_INTERFACE_H +#define METAVISION_HAL_GENX320_ROI_INTERFACE_H + +#include "metavision/hal/facilities/i_roi.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_roi_driver.h" + +namespace Metavision { + +class GenX320RoiInterface : public I_ROI { +public: + GenX320RoiInterface(const std::shared_ptr &driver); + + /// @brief Returns the default device width + /// + /// This values is obtained from the default Device passed in the constructor of the class. + int device_width() const; + + /// @brief Returns the default device height + /// + /// This values is obtained from the default Device passed in the constructor of the class. + int device_height() const; + + /// @brief Applies ROI + /// @param state If true, enables ROI. If false, disables it + /// @warning At least one ROI should have been set before calling this function + /// @return true on success + bool enable(bool state); + + bool is_enabled() const; + + /// @brief Sets the window mode + /// @param mode window mode to set (ROI or RONI) + /// @return true on success + bool set_mode(const Mode &mode); + + I_ROI::Mode get_mode() const; + + /// @brief Gets the maximum number of windows + /// @return the maximum number of windows that can be set via @ref set_windows + size_t get_max_supported_windows_count() const; + + /// @brief Sets multiple ROIs from row and column binary maps + /// + /// The binary maps (std::vector) arguments must have the sensor's dimension + /// + /// @param cols Vector of boolean of size sensor's width representing the binary map of the columns to + /// enable + /// @param rows Vector of boolean of size sensor's height representing the binary map of the rows to + /// enable + /// @return true if input have the correct dimension and the ROI is set correctly, false otherwise + /// @warning For a pixel to be enabled, it must be enabled on both its row and column + bool set_lines(const std::vector &cols, const std::vector &rows); + + std::vector get_windows() const; + +private: + /// @brief Implementation of `set_windows` + /// @param windows A vector of windows to set + /// @return true on success + /// @throw an exception if the size of the vector is higher than the maximum supported number + /// of windows (see @ref get_max_supported_windows_count) + bool set_windows_impl(const std::vector &windows); + + std::shared_ptr driver_; + bool enabled_; +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_GENX320_ROI_INTERFACE_H diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_pixel_mask_interface.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_pixel_mask_interface.h new file mode 100644 index 000000000..f74c183a9 --- /dev/null +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_roi_pixel_mask_interface.h @@ -0,0 +1,36 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_GENX320_ROI_PIXEL_MASK_INTERFACE_H +#define METAVISION_HAL_GENX320_ROI_PIXEL_MASK_INTERFACE_H + +#include +#include "metavision/hal/facilities/i_roi_pixel_mask.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_roi_driver.h" + +namespace Metavision { + +class GenX320RoiPixelMaskInterface : public I_RoiPixelMask { +public: + GenX320RoiPixelMaskInterface(const std::shared_ptr &driver); + + bool set_pixel(const unsigned int &column, const unsigned int &row, const bool &enable); + std::vector> get_pixels() const; + void apply_pixels(); + void reset_pixels(); + +private: + std::shared_ptr driver_; +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_GENX320_ROI_PIXEL_MASK_INTERFACE_H diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/facilities/psee_roi.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/facilities/psee_roi.h index d240476a5..37bc28b42 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/facilities/psee_roi.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/facilities/psee_roi.h @@ -35,6 +35,10 @@ class PseeROI : public I_ROI { /// @return true on success virtual bool set_mode(const Mode &mode) override; + /// @brief Gets the window mode + /// @return the window mode + virtual Mode get_mode() const override; + /// @brief Gets the maximum number of windows /// @return the maximum number of windows that can be set via @ref set_windows virtual size_t get_max_supported_windows_count() const override; @@ -44,7 +48,12 @@ class PseeROI : public I_ROI { /// @return true on success /// @throw an exception if the size of the vector is higher than the maximum supported number /// of windows (see @ref get_max_supported_windows_count) - virtual bool set_windows_impl(const std::vector &windows) override; + virtual bool set_windows_impl(const std::vector &windows) override final; + + /// @brief Gets active ROI/RONI windows + /// + /// @return The vector of active windows + virtual std::vector get_windows() const override; /// @brief Creates several rectangular ROI in bitword register format /// @param vroi Vector of ROI to transform to bitword register format @@ -89,10 +98,10 @@ class PseeROI : public I_ROI { virtual void write_ROI(const std::vector &vroiparams) = 0; private: - void program_ROI_Helper(const std::vector &vroiparams, bool enable); - int device_height_{0}; int device_width_{0}; + + std::vector active_windows_; }; } // namespace Metavision diff --git a/hal_psee_plugins/samples/metavision_imx636_facility_casting_sample/metavision_imx636_facility_casting_sample.cpp b/hal_psee_plugins/samples/metavision_imx636_facility_casting_sample/metavision_imx636_facility_casting_sample.cpp index 9825f3a26..291cd72c5 100644 --- a/hal_psee_plugins/samples/metavision_imx636_facility_casting_sample/metavision_imx636_facility_casting_sample.cpp +++ b/hal_psee_plugins/samples/metavision_imx636_facility_casting_sample/metavision_imx636_facility_casting_sample.cpp @@ -71,7 +71,6 @@ int main(int argc, char *argv[]) { return 1; } - // TODO : MV-551 use I_EventRateActivityFilterModule facility in this sample Metavision::Imx636_LL_Biases *imx636_ll_biases = dynamic_cast(ll_biases); if (!imx636_ll_biases) { std::cerr << "Camera is not an IMX636 camera" << std::endl; diff --git a/hal_psee_plugins/src/devices/CMakeLists.txt b/hal_psee_plugins/src/devices/CMakeLists.txt index 3fd2ce209..104581ce3 100644 --- a/hal_psee_plugins/src/devices/CMakeLists.txt +++ b/hal_psee_plugins/src/devices/CMakeLists.txt @@ -7,25 +7,17 @@ # 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. -add_subdirectory(utils) -add_subdirectory(common) -add_subdirectory(treuzell) -add_subdirectory(gen31) -add_subdirectory(gen41) -add_subdirectory(imx636) -add_subdirectory(imx646) +set(HAL_PSEE_OPEN_PLUGIN_DEVICES gen31 gen41 imx636 imx646 genx320 treuzell + CACHE INTERNAL "Hal plugin open sourced devices") -if(NOT ANDROID) - add_subdirectory(genx320) -endif(NOT ANDROID) +set(HAL_PSEE_CLOSED_PLUGIN_DEVICES saphir sensorlib evk3d + CACHE INTERNAL "Hal plugin close sourced devices") -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/saphir") - add_subdirectory(saphir) -endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/saphir") +set(HAL_PSEE_PLUGIN_DEVICES_COMMON utils common psee-video others) +foreach (hal_device IN LISTS HAL_PSEE_PLUGIN_DEVICES_COMMON HAL_PSEE_OPEN_PLUGIN_DEVICES) + add_subdirectory(${hal_device}) +endforeach() -add_subdirectory(psee-video) -add_subdirectory(others) - -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/sensorlib") - add_subdirectory(sensorlib) -endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/sensorlib") +foreach (hal_closed_device ${HAL_PSEE_CLOSED_PLUGIN_DEVICES}) + add_subdirectory_if_exists(${hal_closed_device}) +endforeach() diff --git a/hal_psee_plugins/src/devices/gen31/gen31_event_rate_noise_filter_module.cpp b/hal_psee_plugins/src/devices/gen31/gen31_event_rate_noise_filter_module.cpp index 7f7214116..daa18d959 100644 --- a/hal_psee_plugins/src/devices/gen31/gen31_event_rate_noise_filter_module.cpp +++ b/hal_psee_plugins/src/devices/gen31/gen31_event_rate_noise_filter_module.cpp @@ -14,6 +14,7 @@ #include "metavision/psee_hw_layer/devices/gen31/gen31_event_rate_noise_filter_module.h" #include "metavision/hal/facilities/i_hw_register.h" +#include "metavision/hal/utils/hal_log.h" #include "metavision/hal/utils/hal_exception.h" #include "utils/psee_hal_plugin_error_code.h" @@ -92,6 +93,27 @@ uint32_t Gen31_EventRateNoiseFilterModule::get_event_rate_threshold() const { return current_threshold_kev_s_; } +Gen31_EventRateNoiseFilterModule::NflThresholds Gen31_EventRateNoiseFilterModule::is_thresholds_supported() const { + return {1, 0, 0, 0}; +} + +bool Gen31_EventRateNoiseFilterModule::set_thresholds( + const Gen31_EventRateNoiseFilterModule::NflThresholds &thresholds_ev_s) { + return set_event_rate_threshold(std::round(thresholds_ev_s.lower_bound_start / 1000.0)); +} + +Gen31_EventRateNoiseFilterModule::NflThresholds Gen31_EventRateNoiseFilterModule::get_thresholds() const { + return {(get_event_rate_threshold() * 1000), 0, 0, 0}; +} + +Gen31_EventRateNoiseFilterModule::NflThresholds Gen31_EventRateNoiseFilterModule::get_min_supported_thresholds() const { + return {(min_event_rate_threshold_kev_s * 1000), 0, 0, 0}; +} + +Gen31_EventRateNoiseFilterModule::NflThresholds Gen31_EventRateNoiseFilterModule::get_max_supported_thresholds() const { + return {(max_event_rate_threshold_kev_s * 1000), 0, 0, 0}; +} + const std::shared_ptr &Gen31_EventRateNoiseFilterModule::get_hw_register() const { return i_hw_register_; } diff --git a/hal_psee_plugins/src/devices/gen31/gen31_roi_command.cpp b/hal_psee_plugins/src/devices/gen31/gen31_roi_command.cpp index ce197502f..7e1810864 100644 --- a/hal_psee_plugins/src/devices/gen31/gen31_roi_command.cpp +++ b/hal_psee_plugins/src/devices/gen31/gen31_roi_command.cpp @@ -82,6 +82,8 @@ bool Gen31ROICommand::enable(bool state) { write_ROI(roi_save_); } + enabled_ = state; + (*register_map_)[prefix_ + "roi_ctrl"]["roi_td_en"] = true; (*register_map_)[prefix_ + "roi_ctrl"]["roi_td_shadow_trigger"] = true; (*register_map_)[prefix_ + "roi_ctrl"]["roi_td_shadow_trigger"] = false; @@ -89,4 +91,8 @@ bool Gen31ROICommand::enable(bool state) { return true; } +bool Gen31ROICommand::is_enabled() const { + return enabled_; +} + } // namespace Metavision diff --git a/hal_psee_plugins/src/devices/gen41/gen41_roi_command.cpp b/hal_psee_plugins/src/devices/gen41/gen41_roi_command.cpp index 10e48a1d3..13ea54df1 100644 --- a/hal_psee_plugins/src/devices/gen41/gen41_roi_command.cpp +++ b/hal_psee_plugins/src/devices/gen41/gen41_roi_command.cpp @@ -21,6 +21,7 @@ namespace Metavision { Gen41ROICommand::Gen41ROICommand(int width, int height, const std::shared_ptr ®map, const std::string &sensor_prefix) : PseeROI(width, height), register_map_(regmap), sensor_prefix_(sensor_prefix), mode_(I_ROI::Mode::ROI) { + roi_save_ = create_ROIs(std::vector({I_ROI::Window(0, 0, width, height)})); reset_to_full_roi(); } @@ -84,16 +85,14 @@ bool Gen41ROICommand::set_mode(const I_ROI::Mode &mode) { return true; } -bool Gen41ROICommand::enable(bool state) { - write_ROI(roi_save_); - if (!state) { - reset_to_full_roi(); +I_ROI::Mode Gen41ROICommand::get_mode() const { + return mode_; +} - } else { - write_ROI(roi_save_); - } +bool Gen41ROICommand::enable(bool state) { + enabled_ = state; - (*register_map_)[sensor_prefix_ + "roi_ctrl"].write_value(vfield{{"roi_td_en", 1}, + (*register_map_)[sensor_prefix_ + "roi_ctrl"].write_value(vfield{{"roi_td_en", state}, {"td_roi_roni_n_en", (mode_ == I_ROI::Mode::ROI)}, {"px_td_rstn", 1}, {"roi_td_shadow_trigger", 1}}); @@ -101,4 +100,8 @@ bool Gen41ROICommand::enable(bool state) { return true; } +bool Gen41ROICommand::is_enabled() const { + return enabled_; +} + } // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/CMakeLists.txt b/hal_psee_plugins/src/devices/genx320/CMakeLists.txt index 1fe7e7c3f..ae9015308 100644 --- a/hal_psee_plugins/src/devices/genx320/CMakeLists.txt +++ b/hal_psee_plugins/src/devices/genx320/CMakeLists.txt @@ -7,12 +7,22 @@ # 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. +if(ANDROID) + return() +endif(ANDROID) + target_sources(metavision_psee_hw_layer_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/genx320_tz_trigger_event.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/genx320_ll_roi.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/genx320_roi_driver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/genx320_roi_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/genx320_roi_pixel_mask_interface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/genx320_ll_biases.cpp ${CMAKE_CURRENT_SOURCE_DIR}/genx320_erc.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/genx320_nfl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/genx320_nfl_driver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/genx320_nfl_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/genx320_dem_driver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/genx320_dem_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/genx320_digital_crop.cpp ) target_sources(metavision_hal_genx320_cx3_system_obj PRIVATE diff --git a/hal_psee_plugins/src/devices/genx320/genx320_cx3_tz_device.cpp b/hal_psee_plugins/src/devices/genx320/genx320_cx3_tz_device.cpp index 4a88e5073..0b3fb6f48 100644 --- a/hal_psee_plugins/src/devices/genx320/genx320_cx3_tz_device.cpp +++ b/hal_psee_plugins/src/devices/genx320/genx320_cx3_tz_device.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "devices/genx320/genx320_cx3_tz_device.h" #include "metavision/psee_hw_layer/boards/treuzell/tz_libusb_board_command.h" @@ -24,13 +25,19 @@ #include "metavision/psee_hw_layer/utils/psee_format.h" #include "metavision/hal/utils/device_builder.h" #include "metavision/psee_hw_layer/devices/genx320/genx320_tz_trigger_event.h" -#include "metavision/psee_hw_layer/devices/genx320/genx320_ll_roi.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_roi_driver.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_roi_interface.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_roi_pixel_mask_interface.h" #include "metavision/psee_hw_layer/devices/genx320/genx320_ll_biases.h" #include "metavision/psee_hw_layer/devices/genx320/genx320_erc.h" -#include "metavision/psee_hw_layer/devices/genx320/genx320_nfl.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_nfl_driver.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_dem_interface.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_digital_crop.h" #include "metavision/psee_hw_layer/devices/common/antiflicker_filter.h" #include "metavision/psee_hw_layer/devices/common/event_trail_filter.h" #include "devices/utils/device_system_id.h" +#include "metavision/psee_hw_layer/utils/register_map.h" namespace Metavision { namespace { @@ -39,12 +46,18 @@ std::string SENSOR_PREFIX = ""; using vfield = std::map; } // namespace +uint32_t get_bitfield(uint32_t value, uint8_t idx, uint8_t size) { + return ((1 << size) - 1) & (value >> idx); +} + TzCx3GenX320::TzCx3GenX320(std::shared_ptr cmd, uint32_t dev_id, std::shared_ptr parent) : TzDevice(cmd, dev_id, parent), TzIssdDevice(issd_genx320es_cx3_sequence), TzDeviceWithRegmap(GenX320ESRegisterMap, GenX320ESRegisterMapSize, ROOT_PREFIX) { sync_mode_ = I_CameraSynchronization::SyncMode::STANDALONE; + iph_mirror_control(true); + temperature_init(); } std::shared_ptr TzCx3GenX320::build(std::shared_ptr cmd, uint32_t dev_id, @@ -65,14 +78,24 @@ bool TzCx3GenX320::can_build(std::shared_ptr cmd, uint32_t void TzCx3GenX320::spawn_facilities(DeviceBuilder &device_builder, const DeviceConfig &device_config) { device_builder.add_facility( std::make_unique(register_map, SENSOR_PREFIX, shared_from_this())); - device_builder.add_facility(std::make_unique(device_config, register_map, SENSOR_PREFIX)); + + auto roi_driver = std::make_shared(320, 320, register_map, SENSOR_PREFIX, device_config); + + device_builder.add_facility(std::make_unique(roi_driver)); + device_builder.add_facility(std::make_unique(roi_driver)); + device_builder.add_facility(std::make_unique(register_map, device_config)); device_builder.add_facility(std::make_unique( std::dynamic_pointer_cast(shared_from_this()), get_sensor_info(), SENSOR_PREFIX)); device_builder.add_facility(std::make_unique( std::dynamic_pointer_cast(shared_from_this()), get_sensor_info(), SENSOR_PREFIX)); device_builder.add_facility(std::make_unique(register_map)); - device_builder.add_facility(std::make_unique(register_map)); + + auto nfl = std::make_shared(register_map); + device_builder.add_facility(std::make_unique(nfl)); + + device_builder.add_facility(std::make_unique(register_map, SENSOR_PREFIX)); + device_builder.add_facility(std::make_unique(register_map, SENSOR_PREFIX)); } TzCx3GenX320::~TzCx3GenX320() {} @@ -149,7 +172,7 @@ void TzCx3GenX320::time_base_config(bool external, bool master) { } } -int TzCx3GenX320::get_temperature() { +void TzCx3GenX320::temperature_init() { // ADC enable (*register_map)["adc_control"].write_value(vfield({{"adc_en", 1}, {"adc_clk_en", 1}})); std::this_thread::sleep_for(std::chrono::microseconds(500)); @@ -171,10 +194,18 @@ int TzCx3GenX320::get_temperature() { // Temperature buf cal (*register_map)["temp_ctrl"].write_value(vfield{{"temp_buf_cal_en", 1}, {"temp_buf_adj_rng", 0}}); std::this_thread::sleep_for(std::chrono::milliseconds(20)); +} + +int TzCx3GenX320::get_temperature() { + MV_HAL_LOG_DEBUG() << "Temperature measurement"; std::list temp_meas = {}; + int meas_samples = 3; + + // ADC Clock enable + (*register_map)["adc_control"]["adc_clk_en"].write_value(1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < meas_samples; i++) { (*register_map)["adc_control"]["adc_start"].write_value(1); std::this_thread::sleep_for(std::chrono::milliseconds(3)); @@ -182,7 +213,7 @@ int TzCx3GenX320::get_temperature() { temp_meas.push_back((val * 0.216) - 54); } - int temp = accumulate(temp_meas.begin(), temp_meas.end(), 0) / 10; + int temp = accumulate(temp_meas.begin(), temp_meas.end(), 0) / meas_samples; // ADC Clock disable (*register_map)["adc_control"]["adc_clk_en"].write_value(0); @@ -190,4 +221,139 @@ int TzCx3GenX320::get_temperature() { return temp; } +int TzCx3GenX320::get_illumination() { + MV_HAL_LOG_DEBUG() << "Illumination measurement"; + bool valid = false; + uint16_t measures = 3; + uint32_t ack_time = 20; + uint32_t ack_step = 10; + + std::vector results(3, 0); + + // We follow 20ms->200ms->2s. + for (int i = 1; i <= measures; i++) { + results = lifo_acquisition(ack_time); + if (results[0] != 1) { + // We failed to converge. + ack_time = ack_time * ack_step; + } else { + valid = true; + (*register_map)["lifo_ton_status"]["lifo_ton_valid"].write_value(1); + break; + } + RegisterMap::Field *my_field((*register_map)["lifo_ton_status"]["lifo_ton_valid"].get_field()); + } + + if (valid) { + int illu = (int)round(exp((11.97 - 0.98 * log(results[2])))); + + return illu; + } else { + MV_HAL_LOG_ERROR() << "Failed to get illumination"; + return -1; + } +} + +void TzCx3GenX320::iph_mirror_control(bool enable) { + (*register_map)["iph_mirr_ctrl"].write_value(vfield({{"iph_mirr_en", enable}, + {"iph_mirr_tbus_in_en", 0}, + {"iph_mirr_calib_en", 0}, + {"iph_mirr_calib_x10_en", 0}, + {"iph_mirr_dft_en", 0}, + {"iph_mirr_dft_sel", 0}})); + + if (enable) { + std::this_thread::sleep_for(std::chrono::microseconds(100)); + } +} + +void TzCx3GenX320::lifo_control(bool enable, bool cnt_enable) { + (*register_map)["lifo_ctrl"].write_value( + vfield({{"lifo_en", enable}, {"lifo_cont_op_en", 1}, {"lifo_dft_mode_en", 0}, {"lifo_timer_en", cnt_enable}})); + + if (enable) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +std::vector TzCx3GenX320::lifo_acquisition(int expected_wait_time = 20) { + // The iph mirror needs to be enabled first + // Default acquisition time is 500 ms to cover low level light condition + // Assuming 25 MHz operation + + lifo_control(true, false); + + // Wait for specified duration for LIFO ton accumulation + std::this_thread::sleep_for(std::chrono::milliseconds(expected_wait_time)); + + // Read LIFO ton register + uint32_t ton_stat = (*register_map)["lifo_ton_status"].read_value(); + + uint8_t valid_index = 0xFF; + RegisterMap::Field *my_field((*register_map)["lifo_ton_status"]["lifo_ton_valid"].get_field()); + + valid_index = my_field->get_start(); + auto overrun_index = (*register_map)["lifo_ton_status"]["lifo_ton_overrun"].get_field()->get_start(); + auto ton_cnt_index = (*register_map)["lifo_ton_status"]["lifo_ton"].get_field()->get_start(); + auto ton_cnt_size = (*register_map)["lifo_ton_status"]["lifo_ton"].get_field()->get_len(); + + auto valid = get_bitfield(ton_stat, valid_index, 1); + auto overrun = get_bitfield(ton_stat, overrun_index, 1); + auto ton_cnt = get_bitfield(ton_stat, ton_cnt_index, ton_cnt_size); + + MV_HAL_LOG_DEBUG() << "Ton status =" << std::hex << "0x" << ton_stat << std::endl; + MV_HAL_LOG_DEBUG() << "Valid bit =" << std::dec << valid << std::endl; + MV_HAL_LOG_DEBUG() << "Overrun bit =" << std::dec << overrun << std::endl; + MV_HAL_LOG_DEBUG() << "Ton cnt bit =" << std::dec << ton_cnt << std::endl; + + lifo_control(false, false); + + std::vector results = {valid, overrun, ton_cnt}; + + return results; +} + +int TzCx3GenX320::get_pixel_dead_time() { + MV_HAL_LOG_DEBUG() << "Pixel dead time measurement"; + auto reg = (*register_map)[SENSOR_PREFIX + "refractory_ctrl"]; + uint32_t refr_val = 0; + uint32_t valid = 0; + uint32_t overrun = 0; + uint32_t count = 0; + + reg.write_value(vfield({ + {"refr_en", 1}, + {"refr_cnt_en", 1}, + })); + + // Erase refractory status bit + reg["refr_overrun"].write_value(1); + + auto valid_index = (*register_map)["refractory_ctrl"]["refr_valid"].get_field()->get_start(); + auto overrun_index = (*register_map)["refractory_ctrl"]["refr_overrun"].get_field()->get_start(); + auto cnt_index = (*register_map)["refractory_ctrl"]["refr_counter"].get_field()->get_start(); + auto cnt_size = (*register_map)["refractory_ctrl"]["refr_counter"].get_field()->get_len(); + + int max_retries = 10; + while (valid == 0) { + if (max_retries == 0) { + throw HalException(HalErrorCode::MaximumRetriesExeeded); + } else { + // Read refractory counter + refr_val = (*register_map)["refractory_ctrl"].read_value(); + valid = get_bitfield(refr_val, valid_index, 1); + overrun = get_bitfield(refr_val, overrun_index, 1); + count = get_bitfield(refr_val, cnt_index, cnt_size); + } + max_retries--; + } + + MV_HAL_LOG_DEBUG() << "Refr status =" << std::hex << "0x" << refr_val << std::endl; + MV_HAL_LOG_DEBUG() << "Valid bit =" << std::dec << valid << std::endl; + MV_HAL_LOG_DEBUG() << "Overrun bit =" << std::dec << overrun << std::endl; + MV_HAL_LOG_DEBUG() << "Count bit =" << std::dec << count << std::endl; + + return count / (25 * 2); +} + } // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/genx320_dem_driver.cpp b/hal_psee_plugins/src/devices/genx320/genx320_dem_driver.cpp new file mode 100644 index 000000000..31052b71f --- /dev/null +++ b/hal_psee_plugins/src/devices/genx320/genx320_dem_driver.cpp @@ -0,0 +1,206 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#include +#include +#include +#include + +#include "metavision/psee_hw_layer/devices/genx320/genx320_dem_driver.h" +#include "metavision/psee_hw_layer/utils/register_map.h" + +using vfield = std::map; + +namespace Metavision { + +GenX320DemDriver::MaskSlot::MaskSlot(const RegAcc ®_ctrl, const RegAcc ®_data) : + reg_ctrl_(reg_ctrl), reg_data_(reg_data), empty_(true) { + vmask_ = {0, 0, 0}; +}; + +void GenX320DemDriver::MaskSlot::update(bool enable) { + reg_ctrl_.write_value(vfield({{"x_group", vmask_.x_group}, {"y", vmask_.y}, {"valid", enable}})); + reg_data_["data"].write_value(vmask_.vector); +} + +bool GenX320DemDriver::MaskSlot::is_valid() { + return reg_ctrl_["valid"].read_value(); +} + +GenX320DemDriver::GenX320DemDriver(const std::shared_ptr ®map, const std::string &prefix) : + regmap_(regmap), prefix_(prefix) { + mslots_.clear(); + + for (unsigned int i = 0; i < NUM_MASK_SLOTS_; i++) { + std::ostringstream reg_mask_ctrl, reg_mask_data; + reg_mask_ctrl << "ro/crazy_pixel_ctrl" << std::dec << std::setw(2) << std::setfill('0') << i; + reg_mask_data << "ro/crazy_pixel_data" << std::dec << std::setw(2) << std::setfill('0') << i; + + RegAcc reg_ctrl = (*regmap_)[reg_mask_ctrl.str()]; + RegAcc reg_data = (*regmap_)[reg_mask_data.str()]; + + MaskSlot slot(reg_ctrl, reg_data); + mslots_.push_back(slot); + } +} + +GenX320DemDriver::VectorMask GenX320DemDriver::vectorize(uint32_t x, uint32_t y) { + // Translate coordinate to vector + uint32_t vector_id = uint32_t(x / 32); + uint32_t vector_val = uint32_t(x % 32); + + GenX320DemDriver::VectorMask vmask = {y, vector_id, uint32_t(1 << vector_val)}; + return vmask; +} + +int GenX320DemDriver::is_power_of_two(unsigned int n) { + return n && (!(n & (n - 1))); +} + +int GenX320DemDriver::find_position(unsigned int n) { + if (!is_power_of_two(n)) + return -1; + + unsigned i = 1, pos = 1; + + // Iterate through bits of n till we find a set bit + // i&n will be non-zero only when 'i' and 'n' have a set bit + // at same position + while (!(i & n)) { + // Unset current bit and set the next bit in 'i' + i = i << 1; + + // increment position + ++pos; + } + + return pos; +} + +std::tuple GenX320DemDriver::extract_coord(VectorMask vmask) { + auto pos = find_position(vmask.vector); + + if (pos != -1) { + return std::make_tuple(vmask.x_group * 32 + (pos - 1), vmask.y); + } else { + return std::make_tuple(-1, -1); + } +} + +bool GenX320DemDriver::set_pixel_filter(uint32_t x, uint32_t y, bool enabled) { + VectorMask vmask = vectorize(x, y); + + // Search if pixel's group is already assigned a slot vector in masks list + std::vector::iterator it = find_if(mslots_.begin(), mslots_.end(), [vmask](MaskSlot slot) { + return ((slot.empty_ == false) && (slot.vmask_.x_group == vmask.x_group) && (slot.vmask_.y == vmask.y)); + }); + + if (it != mslots_.end()) { + // Found matching slot already setup + + if (enabled) { + // Update slot's vector + it->vmask_.vector |= vmask.vector; + it->reg_data_["data"].write_value(it->vmask_.vector); + } else { + // Update slot's vector + it->vmask_.vector &= ~vmask.vector; + it->reg_data_["data"].write_value(it->vmask_.vector); + + if (it->vmask_.vector == 0) { + // Remove entry from mask list to free slot + it->empty_ = true; + it->reg_ctrl_["valid"].write_value(0); + } + } + + } else { + // New slot needs to be assigned + + // Search for first empty slot in masks list + std::vector::iterator first_free = + find_if(mslots_.begin(), mslots_.end(), [](MaskSlot slot) { return (slot.empty_ == true); }); + + if (enabled) { + if (first_free == mslots_.end()) { + // No more slots available + MV_HAL_LOG_WARNING() << "Cannot set new pixel mask. No more slots available"; + return false; + } else { + // Use first empty slot + first_free->vmask_ = vmask; + first_free->empty_ = false; + + // Update registers + first_free->reg_ctrl_.write_value( + vfield({{"x_group", first_free->vmask_.x_group}, {"y", first_free->vmask_.y}, {"valid", 1}})); + + first_free->reg_data_["data"].write_value(first_free->vmask_.vector); + } + } + } + + return true; +} + +bool GenX320DemDriver::set_mask(VectorMask vmask, uint32_t id, bool enable) { + // Update slot + mslots_[id].vmask_ = vmask; + mslots_[id].empty_ = false; + mslots_[id].update(enable); + + return true; +} + +const std::vector &GenX320DemDriver::get_masks() const { + unsigned int i = 0; + + std::for_each(mslots_.begin(), mslots_.end(), [&i](const MaskSlot slot) { + if (slot.empty_ == false) { + std::cout << "Slot " << std::dec << i << ": y=" << slot.vmask_.y << ", x=" << slot.vmask_.x_group + << ", vector=0x" << std::hex << slot.vmask_.vector << std::dec << std::endl; + } else { + std::cout << "Slot " << std::dec << i << ": empty" << std::dec << std::endl; + } + i++; + }); + return mslots_; +} + +GenX320DemDriver::MaskSlot GenX320DemDriver::get_mask(const unsigned int id) const { + return mslots_[id]; +} + +bool GenX320DemDriver::is_pixel_filtered(uint32_t x, uint32_t y) { + VectorMask filter_slot = vectorize(x, y); + + // Search if pixel's group is already assigned a slot vector in masks list + std::vector::iterator it = find_if(mslots_.begin(), mslots_.end(), [filter_slot](MaskSlot n) { + return ((n.empty_ == false) && (n.vmask_.x_group == filter_slot.x_group) && (n.vmask_.y == filter_slot.y)); + }); + + if (it != mslots_.end()) { + // Found matching slot already setup + + if ((it->vmask_.vector && filter_slot.vector) != 0) { + // Pixel is set in the vector + return true; + } else { + // Pixel not selected for filtering + return false; + } + } else { + // No slot setup for pixel coordinates + return false; + } +} + +} // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/genx320_dem_interface.cpp b/hal_psee_plugins/src/devices/genx320/genx320_dem_interface.cpp new file mode 100644 index 000000000..4283ef184 --- /dev/null +++ b/hal_psee_plugins/src/devices/genx320/genx320_dem_interface.cpp @@ -0,0 +1,55 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#include +#include +#include +#include + +#include "metavision/psee_hw_layer/devices/genx320/genx320_dem_interface.h" + +namespace Metavision { + +GenX320DemInterface::GenX320DemInterface(const std::shared_ptr ®map, const std::string &prefix) : + mask_ctrl_(std::make_shared(regmap, prefix)) { + for (unsigned int i = 0; i < NUM_MASK_REGISTERS_; i++) { + pixel_masks_.push_back(std::make_shared(mask_ctrl_, i)); + } +} + +const std::vector &GenX320DemInterface::get_pixel_masks() const { + return pixel_masks_; +} + +GenX320DemInterface::GenX320PixelMask::GenX320PixelMask(const std::shared_ptr &driver, + const unsigned int id) : + driver_(driver), id_(id) {} + +bool GenX320DemInterface::GenX320PixelMask::set_mask(uint32_t x, uint32_t y, bool enabled) { + auto vmask = driver_->vectorize(x, y); + + driver_->set_mask(vmask, id_, enabled); + return true; +} + +std::tuple GenX320DemInterface::GenX320PixelMask::get_mask() const { + auto slot = driver_->get_mask(id_); + auto coord = driver_->extract_coord(slot.vmask_); + auto valid = slot.is_valid(); + + if (std::get<0>(coord) != -1) { + return std::make_tuple(std::get<0>(coord), std::get<1>(coord), valid); + } else { + return std::make_tuple(-1, -1, false); + } +} + +} // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/genx320_digital_crop.cpp b/hal_psee_plugins/src/devices/genx320/genx320_digital_crop.cpp new file mode 100644 index 000000000..a0d2e052a --- /dev/null +++ b/hal_psee_plugins/src/devices/genx320/genx320_digital_crop.cpp @@ -0,0 +1,62 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#include "metavision/hal/utils/hal_exception.h" +#include "metavision/psee_hw_layer/devices/genx320/genx320_digital_crop.h" + +using namespace Metavision; + +GenX320DigitalCrop::GenX320DigitalCrop(const std::shared_ptr ®map, const std::string &prefix) : + enable_((*regmap)[prefix + "ro/oor_ctrl"]["oor_crop_enable"]), + drop_((*regmap)[prefix + "ro/oor_ctrl"]["oor_rm_td"]), + reset_orig_((*regmap)[prefix + "ro/oor_ctrl"]["oor_crop_reset_orig"]), + start_x_((*regmap)[prefix + "ro/oor_start_pos"]["oor_crop_start_x"]), + start_y_((*regmap)[prefix + "ro/oor_start_pos"]["oor_crop_start_y"]), + end_x_((*regmap)[prefix + "ro/oor_end_pos"]["oor_crop_end_x"]), + end_y_((*regmap)[prefix + "ro/oor_end_pos"]["oor_crop_end_y"]) { + drop_.write_value(1); +} + +bool GenX320DigitalCrop::enable(bool state) { + enable_.write_value(state); + return true; +} + +bool GenX320DigitalCrop::is_enabled() const { + return enable_.read_value(); +} + +bool GenX320DigitalCrop::set_window_region(const Region ®ion, bool reset_origin) { + uint32_t start_x, start_y, end_x, end_y; + std::tie(start_x, start_y, end_x, end_y) = region; + + if (start_x > end_x) { + throw HalException(HalErrorCode::InvalidArgument, + "X coordinate of the region end pixel can't be smaller than the X start pixel"); + } + if (start_y > end_y) { + throw HalException(HalErrorCode::InvalidArgument, + "Y coordinate of the region end pixel can't be smaller than the Y start pixel"); + } + + start_x_.write_value(start_x); + start_y_.write_value(start_y); + end_x_.write_value(end_x); + end_y_.write_value(end_y); + + reset_orig_.write_value(reset_origin); + + return true; +} + +GenX320DigitalCrop::Region GenX320DigitalCrop::get_window_region() const { + return {start_x_.read_value(), start_y_.read_value(), end_x_.read_value(), end_y_.read_value()}; +} diff --git a/hal_psee_plugins/src/devices/genx320/genx320_ll_roi.cpp b/hal_psee_plugins/src/devices/genx320/genx320_ll_roi.cpp deleted file mode 100644 index 80a0d4f33..000000000 --- a/hal_psee_plugins/src/devices/genx320/genx320_ll_roi.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#include -#include -#include -#include -#include // floor - -#include "metavision/psee_hw_layer/devices/genx320/genx320_ll_roi.h" -#include "metavision/psee_hw_layer/utils/register_map.h" -#include "metavision/hal/utils/device_config.h" -#include "metavision/hal/utils/hal_log.h" -#include "metavision/hal/utils/hal_exception.h" -#include "metavision/hal/utils/resources_folder.h" -#include "metavision/sdk/base/utils/generic_header.h" - -namespace Metavision { - -GenX320LowLevelRoi::Grid::Grid(int columns, int rows) : columns_(columns), rows_(rows) { - grid_.resize(rows_ * columns_, 0xFFFFFFFF); -} - -std::string GenX320LowLevelRoi::Grid::to_string() const { - std::string out = "\n"; - - for (unsigned int y = 0; y < rows_; y++) { - std::ostringstream row_str; - row_str << "|| " << std::dec << std::setw(3) << y << " || "; - for (unsigned int x = 0; x < columns_; x++) { - row_str << std::hex << std::setw(8) << std::setfill('0') << grid_[y * columns_ + x]; - if (x == columns_ - 1) { - row_str << " ||\n"; - } else { - row_str << " | "; - } - } - out += row_str.str(); - } - return out; -} - -std::tuple GenX320LowLevelRoi::Grid::get_size() const { - return std::make_tuple(columns_, rows_); -} - -void GenX320LowLevelRoi::Grid::set_pixel(const unsigned int &column, const unsigned int &row, const bool &enable) { - std::stringstream ss; - - if (column >= (columns_ * 32)) { - ss << "Column index " << column << " out of range for sensor width (" << columns_ * 32 << ")"; - MV_HAL_LOG_ERROR() << ss.str(); - throw HalException(HalErrorCode::InvalidArgument, ss.str()); - } else if (row >= rows_) { - ss << "Row index " << row << " out of range for sensor height (" << rows_ << ")"; - MV_HAL_LOG_ERROR() << ss.str(); - throw HalException(HalErrorCode::InvalidArgument, ss.str()); - } else { - unsigned int vector_idx = floor(column / 32); - unsigned int bit_idx = column % 32; - unsigned int reg_val = grid_[row * columns_ + vector_idx]; - unsigned int mask = (1 << bit_idx); - - uint32_t saved_fields = reg_val & (~mask); - uint32_t write_field = (enable << bit_idx); - uint32_t new_reg_val = saved_fields | write_field; - - ss << "Pixel selected : " << std::dec << column << " x " << row << "\n"; - ss << "Vector ID : " << vector_idx << "\n"; - ss << "Vector value : 0x" << std::hex << std::setw(8) << std::setfill('0') << reg_val << "\n"; - ss << "Vector bit index : " << std::dec << bit_idx << "\n"; - ss << "Saved fields : 0x" << std::hex << std::setw(8) << std::setfill('0') << saved_fields << "\n"; - ss << "Write fields : 0x" << std::hex << std::setw(8) << std::setfill('0') << write_field << "\n"; - ss << "Write reg : 0x" << std::hex << std::setw(8) << std::setfill('0') << new_reg_val; - - MV_HAL_LOG_DEBUG() << ss.str(); - - grid_[row * columns_ + vector_idx] = new_reg_val; - } -} - -unsigned int &GenX320LowLevelRoi::Grid::get_vector(const unsigned int &vector_id, const unsigned int &row) { - std::stringstream ss; - - if (row >= rows_) { - ss << "Row index " << row << " out of range for LL ROI grid (" << columns_ << "x" << rows_ << ")"; - MV_HAL_LOG_ERROR() << ss.str(); - throw HalException(HalErrorCode::InvalidArgument, ss.str()); - } else if (vector_id >= columns_) { - ss << "Vector index " << vector_id << " out of range for LL ROI grid (" << columns_ << "x" << rows_ << ")"; - MV_HAL_LOG_ERROR() << ss.str(); - throw HalException(HalErrorCode::InvalidArgument, ss.str()); - } else { - return grid_[row * columns_ + vector_id]; - } -} - -void GenX320LowLevelRoi::Grid::set_vector(const unsigned int &vector_id, const unsigned int &row, - const unsigned int &val) { - std::stringstream ss; - - if (row >= rows_) { - ss << "Row index " << row << " out of range for LL ROI grid (" << columns_ << "x" << rows_ << ")"; - MV_HAL_LOG_ERROR() << ss.str(); - throw HalException(HalErrorCode::InvalidArgument, ss.str()); - } else if (vector_id >= columns_) { - ss << "Vector index " << vector_id << " out of range for LL ROI grid (" << columns_ << "x" << rows_ << ")"; - MV_HAL_LOG_ERROR() << ss.str(); - throw HalException(HalErrorCode::InvalidArgument, ss.str()); - } else { - grid_[row * columns_ + vector_id] = val; - } -} - -std::filesystem::path GenX320LowLevelRoi::default_calibration_path() { - static auto calib_path = std::filesystem::path(ResourcesFolder::get_user_path()) / "active_pixel_calib.txt"; - return calib_path; -} - -GenX320LowLevelRoi::GenX320LowLevelRoi(const DeviceConfig &config, const std::shared_ptr ®map, - const std::string &sensor_prefix) : - register_map_(regmap), sensor_prefix_(sensor_prefix) { - // Reset ROI to full resolution - reset(); - - // Disable ROI master and ROI driver - (*register_map_)["roi_master_ctrl"]["roi_master_en"].write_value(0); - (*register_map_)["roi_driver_ctrl"]["roi_driver_en"].write_value(0); - - // Disable roi y (D-Latch enable pin) auto clear (shadow trigger needs to be called for each roi y reg access) - (*register_map_)["roi_ctrl"]["px_roi_halt_programming"].write_value(0); - - if (!config.get("ignore_active_pixel_calibration_data", false)) { - auto calib_path = default_calibration_path(); - if (std::filesystem::exists(calib_path)) { - MV_HAL_LOG_TRACE() << "Found calibration data at" << calib_path; - MV_HAL_LOG_TRACE() << "Loading the calibration data"; - load_calibration_file(calib_path); - } - } -} - -void GenX320LowLevelRoi::reset() { - (*register_map_)["roi_ctrl"]["px_roi_halt_programming"].write_value(1); - (*register_map_)["roi_ctrl"]["px_sw_rstn"].write_value(0); - (*register_map_)["roi_ctrl"]["px_sw_rstn"].write_value(1); - (*register_map_)["roi_ctrl"]["px_roi_halt_programming"].write_value(0); -} - -bool GenX320LowLevelRoi::apply(GenX320LowLevelRoi::Grid &user_grid) { - // ROI X Active column. Pins 'data' of the integrated pixel's Latch. 0: Enable, 1:Disable (default: Enable) - // ROI Y Active row. Pins 'ENABLE' of the integrated pixel's Latch. 0: Disable, 1:Enable (default: Enable) - - auto grid_size = user_grid.get_size(); - auto x_max = std::get<0>(grid_size); - auto y_max = std::get<1>(grid_size); - std::string reg_y_name; - std::string reg_x_name; - unsigned int reg_val = 0; - - if (x_max != 10 || y_max != 320) { - std::stringstream ss; - ss << "Grid size " << x_max << "x" << y_max << " invalid for GenX320. (Expected size : " << 10 << "x" << 320 - << ")"; - MV_HAL_LOG_ERROR() << ss.str(); - throw HalException(HalErrorCode::InvalidArgument, ss.str()); - } - - MV_HAL_LOG_TRACE() << "Applying ROI" << x_max << "x" << y_max; - - (*register_map_)["roi_ctrl"].write_value({{"roi_td_en", 1}, {"px_iphoto_en", 0}}); - - // Iterate over each rows - for (unsigned int y = 0; y < y_max; y++) { - // Compute roi_y register name and select only one row at a time from row index - std::ostringstream reg_id; - reg_id << std::setw(2) << std::setfill('0') << floor(y / 32); - reg_y_name = "roi/td_roi_y" + reg_id.str(); - reg_val = (0x00000001 << (y % 32)); - MV_HAL_LOG_DEBUG() << "ROI Y" << y << std::setw(3) << reg_y_name << ":" << std::hex << std::setw(8) - << std::setfill('0') << reg_val; - - // Send roi y register access, enabling all D-Latches a current row index - (*register_map_)[reg_y_name].write_value(reg_val); - - // Iterate over each columns composed of 32 bits vectors - for (unsigned int x = 0; x < x_max; x++) { - // Compute roi_x register name from column index - std::ostringstream reg_id; - reg_id << std::setw(2) << std::setfill('0') << x; - reg_x_name = "roi/td_roi_x" + reg_id.str(); - MV_HAL_LOG_DEBUG() << "ROI" << y << "x" << x << ":" << std::hex << std::setw(8) << std::setfill('0') - << ~user_grid.get_vector(x, y); - - // Send roi x register access, setting all D-Latches data lanes from given user config on current row. - (*register_map_)[reg_x_name].write_value(~user_grid.get_vector(x, y)); - } - - // Apply configuration to the hardware by triggering D-Latches toggling of their respective output - (*register_map_)["roi_ctrl"]["roi_td_shadow_trigger"].write_value(1); - - // Clear roi y register. Deselect current row - (*register_map_)[reg_y_name].write_value(0); - (*register_map_)["roi_ctrl"]["roi_td_shadow_trigger"].write_value(1); - } - - // Disable ROI - (*register_map_)["roi_ctrl"]["roi_td_en"].write_value(0); - - return true; -} - -bool GenX320LowLevelRoi::load_calibration_file(const std::filesystem::path &path) { - std::ifstream ifs(path); - if (!ifs.is_open()) { - return false; - } - - Grid g(10, 320); - GenericHeader header(ifs); - std::string line; - while (std::getline(ifs, line)) { - int x, y; - if (std::istringstream(line) >> x >> y) { - g.set_pixel(x, y, false); - } - } - apply(g); - - return true; -} - -} // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/genx320_nfl.cpp b/hal_psee_plugins/src/devices/genx320/genx320_nfl.cpp deleted file mode 100644 index 2bb73813d..000000000 --- a/hal_psee_plugins/src/devices/genx320/genx320_nfl.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#include -#include - -#include "metavision/psee_hw_layer/devices/genx320/genx320_nfl.h" -#include "metavision/psee_hw_layer/utils/register_map.h" -#include "metavision/hal/utils/hal_exception.h" -#include "utils/psee_hal_plugin_error_code.h" - -using vfield = std::map; - -namespace Metavision { - -constexpr uint32_t GenX320NoiseFilter::min_time_window_us_; -constexpr uint32_t GenX320NoiseFilter::max_time_window_us_; -constexpr uint32_t GenX320NoiseFilter::min_event_rate_threshold_kev_s; -constexpr uint32_t GenX320NoiseFilter::max_event_rate_threshold_kev_s; - -GenX320NoiseFilter::GenX320NoiseFilter(const std::shared_ptr ®ister_map) : - register_map_(register_map) {} - -bool GenX320NoiseFilter::enable(bool enable_filter) { - (*register_map_)["nfl/pipeline_control"].write_value(vfield{{"enable", 1}, {"bypass", 1}}); - - (*register_map_)["nfl/insert_drop_monitoring"]["en"].write_value(0); - (*register_map_)["nfl/max_voxel_threshold_on"]["val"].write_value(max_pixel_event_threshold_on); - (*register_map_)["nfl/max_voxel_threshold_off"]["val"].write_value(max_pixel_event_threshold_off); - get_event_rate_threshold(); - - (*register_map_)["nfl/pipeline_control"]["bypass"].write_value(!enable_filter); - - return true; -} - -bool GenX320NoiseFilter::is_enabled() const { - return !(*register_map_)["nfl/pipeline_control"]["bypass"].read_value(); -} - -bool GenX320NoiseFilter::set_time_window(uint32_t window_length_us) { - if (window_length_us < min_time_window_us_ || window_length_us > max_time_window_us_) { - return false; - } - - (*register_map_)["nfl/reference_period"]["val"].write_value(window_length_us); - return true; -} - -uint32_t GenX320NoiseFilter::get_time_window() const { - return (*register_map_)["nfl/reference_period"]["val"].read_value(); -} - -bool GenX320NoiseFilter::set_event_rate_threshold(uint32_t threshold_kev_s) { - if (threshold_kev_s < min_event_rate_threshold_kev_s || threshold_kev_s > max_event_rate_threshold_kev_s) { - return false; - } - - set_time_window(max_time_window_us_); // Maximum time resolution to ensures we are closest to the user input - // threshold (1023 us latency) though it is invisible in term of user - // experience. - - auto min_event_count_in_time_shifting_window = - std::round((threshold_kev_s / 1000.) * get_time_window()); // ev per microseconds - - (*register_map_)["nfl/min_voxel_threshold_off"]["val"].write_value(min_event_count_in_time_shifting_window + 100); - (*register_map_)["nfl/min_voxel_threshold_on"]["val"].write_value(min_event_count_in_time_shifting_window); - - get_event_rate_threshold(); - return true; -} - -uint32_t GenX320NoiseFilter::get_event_rate_threshold() const { - current_threshold_kev_s_ = - std::round(((*register_map_)["nfl/min_voxel_threshold_off"]["val"].read_value() * 1000.) / get_time_window()); - return current_threshold_kev_s_; -} - -} // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/genx320_nfl_driver.cpp b/hal_psee_plugins/src/devices/genx320/genx320_nfl_driver.cpp new file mode 100644 index 000000000..cc668310e --- /dev/null +++ b/hal_psee_plugins/src/devices/genx320/genx320_nfl_driver.cpp @@ -0,0 +1,184 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#include +#include + +#include "metavision/psee_hw_layer/devices/genx320/genx320_nfl_driver.h" +#include "metavision/psee_hw_layer/utils/register_map.h" +#include "metavision/hal/utils/hal_exception.h" +#include "utils/psee_hal_plugin_error_code.h" + +using vfield = std::map; + +namespace Metavision { + +GenX320NflDriver::GenX320NflDriver(const std::shared_ptr ®ister_map) : register_map_(register_map) { + set_time_window(1000); + auto min_thres = get_min_supported_thresholds(); + auto max_thres = get_max_supported_thresholds(); + set_thresholds({min_thres.lower_bound_start, min_thres.lower_bound_stop, max_thres.upper_bound_start, + max_thres.upper_bound_stop}); +} + +bool GenX320NflDriver::enable(bool enable_filter) { + (*register_map_)["nfl/pipeline_control"].write_value(vfield{{"enable", 1}, {"bypass", 1}}); + + (*register_map_)["nfl/insert_drop_monitoring"]["en"].write_value(0); + (*register_map_)["nfl/pipeline_control"]["bypass"].write_value(!enable_filter); + + return true; +} + +bool GenX320NflDriver::is_enabled() const { + return !(*register_map_)["nfl/pipeline_control"]["bypass"].read_value(); +} + +bool GenX320NflDriver::set_time_window(uint32_t window_length_us) { + // Using higher time resolution will ensure we are closest to the user input + // threshold. Higher time window also increase latency. Though it is mostly invisible for the user given the + // maximum value is 1024 us. + + if (window_length_us < min_time_window_us || window_length_us > max_time_window_us) { + return false; + } + + (*register_map_)["nfl/reference_period"]["val"].write_value(window_length_us); + return true; +} + +uint32_t GenX320NflDriver::get_time_window() const { + return (*register_map_)["nfl/reference_period"]["val"].read_value(); +} + +uint32_t GenX320NflDriver::compute_cd_threshold(uint32_t event_rate_ev_s) const { + return std::round((event_rate_ev_s / 1000000.) * get_time_window()); +} + +uint32_t GenX320NflDriver::compute_event_rate(uint32_t threshold) const { + return std::round((threshold * 1000000.) / get_time_window()); +} + +GenX320NflDriver::NflThresholds GenX320NflDriver::is_thresholds_supported() const { + NflThresholds thresholds_valid; + + thresholds_valid.lower_bound_start = 1; + thresholds_valid.lower_bound_stop = 1; + thresholds_valid.upper_bound_start = 1; + thresholds_valid.upper_bound_stop = 1; + + return thresholds_valid; +} + +bool GenX320NflDriver::set_thresholds(const GenX320NflDriver::NflThresholds &thresholds_ev_s) { + // Set lower bound start + auto thres = compute_cd_threshold(thresholds_ev_s.lower_bound_start); + (*register_map_)["nfl/min_voxel_threshold_on"]["val"].write_value(thres); + + // Set lower bound stop + thres = compute_cd_threshold(thresholds_ev_s.lower_bound_stop); + (*register_map_)["nfl/min_voxel_threshold_off"]["val"].write_value(thres); + + // Set upper bound start + auto max_evt_rate = get_max_supported_thresholds().upper_bound_start; + thres = compute_cd_threshold(thresholds_ev_s.upper_bound_start); + + if (thres > max_register_value) { + std::ostringstream err_msg; + err_msg << "NFL upper bound event rate threshold '" << thresholds_ev_s.upper_bound_start + << " evt/s' exceeds register maximum allowed value."; + MV_HAL_LOG_ERROR() << err_msg.str(); + return false; + } + + if (thresholds_ev_s.upper_bound_start > max_evt_rate) { + std::ostringstream warn_msg; + warn_msg << "NFL upper bound event rate threshold selected '" << thresholds_ev_s.upper_bound_start + << " evt/s' exceeds highest settings."; + MV_HAL_LOG_WARNING() << warn_msg.str(); + warn_msg.clear(); + warn_msg.str(""); + warn_msg << "NFL upper bound will be capped at '" << max_evt_rate << " evt/s'"; + MV_HAL_LOG_WARNING() << warn_msg.str(); + thres = compute_cd_threshold(max_evt_rate); + MV_HAL_LOG_INFO() << "Threshold = 0x" << std::hex << thres << std::dec; + } + + (*register_map_)["nfl/max_voxel_threshold_on"]["val"].write_value(thres); + + // Set upper bound stop + max_evt_rate = get_max_supported_thresholds().upper_bound_stop; + thres = compute_cd_threshold(thresholds_ev_s.upper_bound_stop); + + if (thres > max_register_value) { + std::ostringstream err_msg; + err_msg << "NFL upper bound event rate threshold '" << thresholds_ev_s.upper_bound_stop + << " evt/s' exceeds register maximum allowed value."; + MV_HAL_LOG_ERROR() << err_msg.str(); + return false; + } + + if (thresholds_ev_s.upper_bound_stop > max_evt_rate) { + std::ostringstream warn_msg; + warn_msg << "NFL upper bound event rate threshold selected '" << thresholds_ev_s.upper_bound_stop + << " evt/s' exceeds highest settings."; + MV_HAL_LOG_WARNING() << warn_msg.str(); + warn_msg.clear(); + warn_msg.str(""); + warn_msg << "NFL upper bound will be capped at '" << max_evt_rate << " evt/s'"; + MV_HAL_LOG_WARNING() << warn_msg.str(); + thres = compute_cd_threshold(max_evt_rate); + MV_HAL_LOG_INFO() << "Threshold = 0x" << std::hex << thres << std::dec; + } + + (*register_map_)["nfl/max_voxel_threshold_off"]["val"].write_value(thres); + + return true; +} + +GenX320NflDriver::NflThresholds GenX320NflDriver::get_thresholds() const { + GenX320NflDriver::NflThresholds thres_list; + + thres_list.lower_bound_start = + compute_event_rate((*register_map_)["nfl/min_voxel_threshold_on"]["val"].read_value()); + thres_list.lower_bound_stop = + compute_event_rate((*register_map_)["nfl/min_voxel_threshold_off"]["val"].read_value()); + thres_list.upper_bound_start = + compute_event_rate((*register_map_)["nfl/max_voxel_threshold_on"]["val"].read_value()); + thres_list.upper_bound_stop = + compute_event_rate((*register_map_)["nfl/max_voxel_threshold_off"]["val"].read_value()); + + return thres_list; +} + +GenX320NflDriver::NflThresholds GenX320NflDriver::get_min_supported_thresholds() const { + GenX320NflDriver::NflThresholds thres; + + thres.lower_bound_start = compute_event_rate(min_pixel_event_threshold_on); + thres.lower_bound_stop = compute_event_rate(min_pixel_event_threshold_off); + thres.upper_bound_start = compute_event_rate(min_pixel_event_threshold_on); + thres.upper_bound_stop = compute_event_rate(min_pixel_event_threshold_off); + + return thres; +} + +GenX320NflDriver::NflThresholds GenX320NflDriver::get_max_supported_thresholds() const { + GenX320NflDriver::NflThresholds thres; + + thres.lower_bound_start = compute_event_rate(max_pixel_event_threshold_on); + thres.lower_bound_stop = compute_event_rate(max_pixel_event_threshold_off); + thres.upper_bound_start = compute_event_rate(max_pixel_event_threshold_on); + thres.upper_bound_stop = compute_event_rate(max_pixel_event_threshold_off); + + return thres; +} + +} // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/genx320_nfl_interface.cpp b/hal_psee_plugins/src/devices/genx320/genx320_nfl_interface.cpp new file mode 100644 index 000000000..9d7fbb8fd --- /dev/null +++ b/hal_psee_plugins/src/devices/genx320/genx320_nfl_interface.cpp @@ -0,0 +1,61 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#include +#include "metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h" + +namespace Metavision { + +GenX320NflInterface::GenX320NflInterface(const std::shared_ptr &driver) : driver_(driver) {} + +bool GenX320NflInterface::enable(bool enable_filter) { + return driver_->enable(enable_filter); +} + +bool GenX320NflInterface::is_enabled() const { + return driver_->is_enabled(); +} + +bool GenX320NflInterface::set_event_rate_threshold(uint32_t threshold_Kev_s) { + auto thres_ev_s = threshold_Kev_s * 1000; + auto thres_max = driver_->get_max_supported_thresholds(); + bool valid = driver_->set_thresholds( + {thres_ev_s, thres_ev_s + 10000, thres_max.upper_bound_start, thres_max.upper_bound_stop}); + + return valid; +} + +uint32_t GenX320NflInterface::get_event_rate_threshold() const { + auto thres_ev_s = driver_->get_thresholds().lower_bound_start; + return std::round(thres_ev_s / 1000.0); +} + +I_EventRateActivityFilterModule::thresholds GenX320NflInterface::is_thresholds_supported() const { + return driver_->is_thresholds_supported(); +} + +bool GenX320NflInterface::set_thresholds(const I_EventRateActivityFilterModule::thresholds &thresholds_ev_s) { + return driver_->set_thresholds(thresholds_ev_s); +} + +I_EventRateActivityFilterModule::thresholds GenX320NflInterface::get_thresholds() const { + return driver_->get_thresholds(); +} + +I_EventRateActivityFilterModule::thresholds GenX320NflInterface::get_min_supported_thresholds() const { + return driver_->get_min_supported_thresholds(); +} + +I_EventRateActivityFilterModule::thresholds GenX320NflInterface::get_max_supported_thresholds() const { + return driver_->get_max_supported_thresholds(); +} + +} // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/genx320_roi_driver.cpp b/hal_psee_plugins/src/devices/genx320/genx320_roi_driver.cpp new file mode 100644 index 000000000..91fac8b13 --- /dev/null +++ b/hal_psee_plugins/src/devices/genx320/genx320_roi_driver.cpp @@ -0,0 +1,420 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#include +#include // floor +#include + +#include "metavision/psee_hw_layer/devices/genx320/genx320_roi_driver.h" +#include "metavision/hal/utils/hal_log.h" +#include "metavision/hal/utils/hal_exception.h" +#include "metavision/hal/utils/resources_folder.h" +#include "metavision/sdk/base/utils/generic_header.h" + +using vfield = std::map; + +namespace Metavision { + +GenX320RoiDriver::Grid::Grid(int columns, int rows) : columns_(columns), rows_(rows) { + grid_.resize(rows_ * columns_, 0xFFFFFFFF); +} + +std::string GenX320RoiDriver::Grid::to_string() const { + std::string out = "\n"; + + for (unsigned int y = 0; y < rows_; y++) { + std::ostringstream row_str; + row_str << "|| " << std::dec << std::setw(3) << y << " || "; + for (unsigned int x = 0; x < columns_; x++) { + row_str << std::hex << std::setw(8) << std::setfill('0') << grid_[y * columns_ + x]; + if (x == columns_ - 1) { + row_str << " ||\n"; + } else { + row_str << " | "; + } + } + out += row_str.str(); + } + return out; +} + +std::tuple GenX320RoiDriver::Grid::get_size() const { + return std::make_tuple(columns_, rows_); +} + +void GenX320RoiDriver::Grid::clear() { + for (unsigned int y = 0; y < rows_; y++) { + for (unsigned int x = 0; x < columns_; x++) { + grid_[y * columns_ + x] = 0xFFFFFFFF; + } + } +} + +void GenX320RoiDriver::Grid::set_pixel(const unsigned int &column, const unsigned int &row, const bool &enable) { + std::stringstream ss; + + if (column >= (columns_ * 32)) { + ss << "Column index " << column << " out of range for sensor width (" << columns_ * 32 << ")"; + MV_HAL_LOG_ERROR() << ss.str(); + throw HalException(HalErrorCode::InvalidArgument, ss.str()); + } else if (row >= rows_) { + ss << "Row index " << row << " out of range for sensor height (" << rows_ << ")"; + MV_HAL_LOG_ERROR() << ss.str(); + throw HalException(HalErrorCode::InvalidArgument, ss.str()); + } else { + unsigned int vector_idx = floor(column / 32); + unsigned int bit_idx = column % 32; + unsigned int reg_val = grid_[row * columns_ + vector_idx]; + unsigned int mask = (1 << bit_idx); + + uint32_t saved_fields = reg_val & (~mask); + uint32_t write_field = (enable << bit_idx); + uint32_t new_reg_val = saved_fields | write_field; + + ss << "Pixel selected : " << std::dec << column << " x " << row << "\n"; + ss << "Vector ID : " << vector_idx << "\n"; + ss << "Vector value : 0x" << std::hex << std::setw(8) << std::setfill('0') << reg_val << "\n"; + ss << "Vector bit index : " << std::dec << bit_idx << "\n"; + ss << "Saved fields : 0x" << std::hex << std::setw(8) << std::setfill('0') << saved_fields << "\n"; + ss << "Write fields : 0x" << std::hex << std::setw(8) << std::setfill('0') << write_field << "\n"; + ss << "Write reg : 0x" << std::hex << std::setw(8) << std::setfill('0') << new_reg_val; + + MV_HAL_LOG_DEBUG() << ss.str(); + + grid_[row * columns_ + vector_idx] = new_reg_val; + } +} + +unsigned int &GenX320RoiDriver::Grid::get_vector(const unsigned int &vector_id, const unsigned int &row) { + std::stringstream ss; + + if (row >= rows_) { + ss << "Row index " << row << " out of range for LL ROI grid (" << columns_ << "x" << rows_ << ")"; + MV_HAL_LOG_ERROR() << ss.str(); + throw HalException(HalErrorCode::InvalidArgument, ss.str()); + } else if (vector_id >= columns_) { + ss << "Vector index " << vector_id << " out of range for LL ROI grid (" << columns_ << "x" << rows_ << ")"; + MV_HAL_LOG_ERROR() << ss.str(); + throw HalException(HalErrorCode::InvalidArgument, ss.str()); + } else { + return grid_[row * columns_ + vector_id]; + } +} + +void GenX320RoiDriver::Grid::set_vector(const unsigned int &vector_id, const unsigned int &row, + const unsigned int &val) { + std::stringstream ss; + + if (row >= rows_) { + ss << "Row index " << row << " out of range for LL ROI grid (" << columns_ << "x" << rows_ << ")"; + MV_HAL_LOG_ERROR() << ss.str(); + throw HalException(HalErrorCode::InvalidArgument, ss.str()); + } else if (vector_id >= columns_) { + ss << "Vector index " << vector_id << " out of range for LL ROI grid (" << columns_ << "x" << rows_ << ")"; + MV_HAL_LOG_ERROR() << ss.str(); + throw HalException(HalErrorCode::InvalidArgument, ss.str()); + } else { + grid_[row * columns_ + vector_id] = val; + } +} + +std::filesystem::path GenX320RoiDriver::default_calibration_path() { + static auto calib_path = std::filesystem::path(ResourcesFolder::get_user_path()) / "active_pixel_calib.txt"; + return calib_path; +} + +GenX320RoiDriver::GenX320RoiDriver(int width, int height, const std::shared_ptr ®map, + const std::string &sensor_prefix, const DeviceConfig &config) : + register_map_(regmap), sensor_prefix_(sensor_prefix), mode_(I_ROI::Mode::ROI), roi_window_cnt_(0), grid_(10, 320) { + set_driver_mode(GenX320RoiDriver::DriverMode::MASTER); + reset_to_full_roi(); + if (!config.get("ignore_active_pixel_calibration_data", false)) { + auto calib_path = default_calibration_path(); + if (std::filesystem::exists(calib_path)) { + MV_HAL_LOG_TRACE() << "Found calibration data at" << calib_path; + MV_HAL_LOG_TRACE() << "Loading the calibration data"; + set_driver_mode(GenX320RoiDriver::DriverMode::LATCH); + load_calibration_file(calib_path); + } + } +} + +bool GenX320RoiDriver::set_pixel(const unsigned int &column, const unsigned int &row, const bool &enable) { + grid_.set_pixel(column, row, enable); + return true; +} + +bool GenX320RoiDriver::set_grid(GenX320RoiDriver::Grid &user_grid) { + auto grid_size = user_grid.get_size(); + auto x_max = std::get<0>(grid_size); + auto y_max = std::get<1>(grid_size); + + if (x_max != 10 || y_max != 320) { + std::stringstream ss; + ss << "Grid size " << x_max << "x" << y_max << " invalid for GenX320. (Expected size : " << 10 << "x" << 320 + << ")"; + MV_HAL_LOG_ERROR() << ss.str(); + return false; + } else { + grid_ = user_grid; + return true; + } +} + +void GenX320RoiDriver::apply_grid() { + // ROI X Active column. Pins 'data' of the integrated pixel's Latch. 0: Enable, 1:Disable (default: Enable) + // ROI Y Active row. Pins 'ENABLE' of the integrated pixel's Latch. 0: Disable, 1:Enable (default: Enable) + + std::string reg_y_name; + std::string reg_x_name; + unsigned int reg_val = 0; + + // Iterate over each rows + for (unsigned int y = 0; y < 320; y++) { + // Compute roi_y register name and select only one row at a time from row index + std::ostringstream reg_id; + reg_id << std::setw(2) << std::setfill('0') << floor(y / 32); + reg_y_name = "roi/td_roi_y" + reg_id.str(); + reg_val = (0x00000001 << (y % 32)); + MV_HAL_LOG_DEBUG() << "ROI Y" << y << std::setw(3) << reg_y_name << ":" << std::hex << std::setw(8) + << std::setfill('0') << reg_val; + + // Send roi y register access, enabling all D-Latches a current row index + (*register_map_)[reg_y_name].write_value(reg_val); + + // Iterate over each columns composed of 32 bits vectors + for (unsigned int x = 0; x < 10; x++) { + // Compute roi_x register name from column index + std::ostringstream reg_id; + reg_id << std::setw(2) << std::setfill('0') << x; + reg_x_name = "roi/td_roi_x" + reg_id.str(); + MV_HAL_LOG_DEBUG() << "ROI" << y << "x" << x << ":" << std::hex << std::setw(8) << std::setfill('0') + << ~grid_.get_vector(x, y); + + // Send roi x register access, setting all D-Latches data lanes from given user config on current row. + (*register_map_)[reg_x_name].write_value(~grid_.get_vector(x, y)); + } + + // Apply configuration to the hardware by triggering D-Latches toggling of their respective output + (*register_map_)["roi_ctrl"]["roi_td_shadow_trigger"].write_value(0); + (*register_map_)["roi_ctrl"]["roi_td_shadow_trigger"].write_value(1); + + // Clear roi y register. Deselect current row + (*register_map_)[reg_y_name].write_value(0); + (*register_map_)["roi_ctrl"]["roi_td_shadow_trigger"].write_value(0); + (*register_map_)["roi_ctrl"]["roi_td_shadow_trigger"].write_value(1); + } + + (*register_map_)["roi_ctrl"]["roi_td_shadow_trigger"].write_value(0); +} + +bool GenX320RoiDriver::load_calibration_file(const std::filesystem::path &path) { + std::ifstream ifs(path); + if (!ifs.is_open()) { + return false; + } + + Grid g(10, 320); + GenericHeader header(ifs); + std::string line; + while (std::getline(ifs, line)) { + int x, y; + if (std::istringstream(line) >> x >> y) { + g.set_pixel(x, y, false); + } + } + set_grid(g); + apply_grid(); + + return true; +} + +int GenX320RoiDriver::device_width() const { + return device_width_; +} + +int GenX320RoiDriver::device_height() const { + return device_height_; +} + +unsigned int GenX320RoiDriver::get_max_windows_count() const { + return 18; +} + +bool GenX320RoiDriver::set_windows(const std::vector &windows) { + roi_window_cnt_ = windows.size(); + main_window_ = windows[0]; + + for (unsigned int i = 0; i < roi_window_cnt_; i++) { + int x_min = windows[i].x; + int y_min = windows[i].y; + int x_max = x_min + windows[i].width; + int y_max = y_min + windows[i].height; + + std::string win_x_coord = "roi_win_x" + std::to_string(i); + std::string win_y_coord = "roi_win_y" + std::to_string(i); + + (*register_map_)[sensor_prefix_ + win_x_coord].write_value( + vfield{{"roi_win_start_x", x_min}, {"roi_win_end_p1_x", x_max}}); + (*register_map_)[sensor_prefix_ + win_y_coord].write_value( + vfield{{"roi_win_start_y", y_min}, {"roi_win_end_p1_y", y_max}}); + } + + return true; +} + +bool GenX320RoiDriver::set_lines(const std::vector &cols, const std::vector &rows) { + std::vector columns_sel(10, 0); + uint32_t val = 0; + uint32_t vect_id = 0; + + grid_.clear(); + + for (unsigned int i = 0; i <= cols.size(); i++) { + if ((i % 32) == 0) { + if (i != 0) { + columns_sel[vect_id] = val; + vect_id++; + val = 0; + } else if (i == cols.size()) { + columns_sel[vect_id] = val; + break; + } + } + val += (cols[i] << (i % 32)); + } + + for (unsigned int y = 0; y < 320; y++) { + if (rows[y] == true) { + for (unsigned int x = 0; x < 10; x++) { + grid_.set_vector(x, y, columns_sel[x]); + } + } else { + for (unsigned int x = 0; x < 10; x++) { + grid_.set_vector(x, y, 0); + } + } + } + return true; +} + +void GenX320RoiDriver::apply_windows(unsigned int window_count) { + (*register_map_)[sensor_prefix_ + "roi_ctrl"]["px_roi_halt_programming"].write_value(0); + + (*register_map_)[sensor_prefix_ + "roi_master_ctrl"].write_value( + vfield{{"roi_master_en", 1}, + {"roi_master_run", 1}, + {"roi_master_mode", static_cast::type>(mode_)}, + {"roi_win_nb", window_count}}); +} + +void GenX320RoiDriver::reset_to_full_roi() { + auto default_window = I_ROI::Window(0, 0, 320, 320); + + (*register_map_)[sensor_prefix_ + "roi_win_x0"].write_value( + vfield{{"roi_win_start_x", default_window.x}, {"roi_win_end_p1_x", default_window.width}}); + (*register_map_)[sensor_prefix_ + "roi_win_y0"].write_value( + vfield{{"roi_win_start_y", default_window.y}, {"roi_win_end_p1_y", default_window.height}}); + + I_ROI::Mode save_mode = mode_; + mode_ = I_ROI::Mode::ROI; + apply_windows(1); + mode_ = save_mode; +} + +bool GenX320RoiDriver::set_roi_mode(const I_ROI::Mode &mode) { + mode_ = mode; + return true; +} + +I_ROI::Mode GenX320RoiDriver::get_roi_mode() const { + return mode_; +} + +bool GenX320RoiDriver::set_driver_mode(const GenX320RoiDriver::DriverMode &driver_mode) { + driver_mode_ = driver_mode; + + (*register_map_)[sensor_prefix_ + "roi_ctrl"]["roi_td_en"].write_value(1); + (*register_map_)[sensor_prefix_ + "roi_ctrl"]["px_iphoto_en"].write_value(0); + (*register_map_)[sensor_prefix_ + "roi_ctrl"]["px_sw_rstn"].write_value(1); + (*register_map_)[sensor_prefix_ + "roi_ctrl"]["roi_td_shadow_trigger"].write_value(0); + + if (driver_mode_ == GenX320RoiDriver::DriverMode::MASTER) { + (*register_map_)[sensor_prefix_ + "roi_master_chicken_bit"]["roi_driver_register_if_en"].write_value(0); + (*register_map_)[sensor_prefix_ + "roi_ctrl"]["px_roi_halt_programming"].write_value(0); + (*register_map_)[sensor_prefix_ + "roi_master_ctrl"].write_value( + vfield{{"roi_master_en", 1}, {"roi_master_run", 0}}); + } + + return true; +} + +bool GenX320RoiDriver::enable(bool state) { + if (!state) { + reset_to_full_roi(); + } else { + if (driver_mode_ == GenX320RoiDriver::DriverMode::MASTER) { + // Re-apply first roi + (*register_map_)[sensor_prefix_ + "roi_win_x0"].write_value( + vfield{{"roi_win_start_x", main_window_.x}, {"roi_win_end_p1_x", main_window_.x + main_window_.width}}); + (*register_map_)[sensor_prefix_ + "roi_win_y0"].write_value(vfield{ + {"roi_win_start_y", main_window_.y}, {"roi_win_end_p1_y", main_window_.x + main_window_.height}}); + + apply_windows(roi_window_cnt_); + } else { + apply_grid(); + } + } + + return true; +} + +std::vector GenX320RoiDriver::get_windows() const { + std::vector roi_win_list; + + for (unsigned int i = 0; i < roi_window_cnt_; i++) { + std::string win_x_coord = "roi_win_x" + std::to_string(i); + std::string win_y_coord = "roi_win_y" + std::to_string(i); + + auto x_min = (*register_map_)[sensor_prefix_ + win_x_coord]["roi_win_start_x"].read_value(); + auto x_max = (*register_map_)[sensor_prefix_ + win_x_coord]["roi_win_end_p1_x"].read_value(); + + auto y_min = (*register_map_)[sensor_prefix_ + win_y_coord]["roi_win_start_y"].read_value(); + auto y_max = (*register_map_)[sensor_prefix_ + win_y_coord]["roi_win_end_p1_y"].read_value(); + + I_ROI::Window my_win(x_min, y_min, x_max - x_min, y_max - y_min); + roi_win_list.push_back(my_win); + } + return roi_win_list; +} + +void GenX320RoiDriver::print_windows_config() { + std::cout << "Windows cnt = " << roi_window_cnt_ << std::endl; + + auto win_list = get_windows(); + + for (unsigned int i = 0; i < roi_window_cnt_; i++) { + auto window = win_list[i]; + + std::cout << "Window " << i << " = " << window.x << ", " << window.y << " (" << window.width << ", " + << window.height << ")" << std::endl; + } +} + +GenX320RoiDriver::Grid GenX320RoiDriver::get_grid() const { + return grid_; +} + +void GenX320RoiDriver::print_grid_config() { + std::cout << grid_.to_string() << std::endl; +} + +} // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/genx320_roi_interface.cpp b/hal_psee_plugins/src/devices/genx320/genx320_roi_interface.cpp new file mode 100644 index 000000000..9df383dbe --- /dev/null +++ b/hal_psee_plugins/src/devices/genx320/genx320_roi_interface.cpp @@ -0,0 +1,62 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#include "metavision/psee_hw_layer/devices/genx320/genx320_roi_interface.h" + +namespace Metavision { + +GenX320RoiInterface::GenX320RoiInterface(const std::shared_ptr &driver) : + driver_(driver), enabled_(false) {} + +int GenX320RoiInterface::device_width() const { + return 320; +} + +int GenX320RoiInterface::device_height() const { + return 320; +} + +bool GenX320RoiInterface::enable(bool state) { + enabled_ = state; + return driver_->enable(state); +} + +bool GenX320RoiInterface::is_enabled() const { + return enabled_; +} + +bool GenX320RoiInterface::set_mode(const Mode &mode) { + return driver_->set_roi_mode(mode); +} + +I_ROI::Mode GenX320RoiInterface::get_mode() const { + return driver_->get_roi_mode(); +} + +size_t GenX320RoiInterface::get_max_supported_windows_count() const { + return driver_->get_max_windows_count(); +} + +bool GenX320RoiInterface::set_lines(const std::vector &cols, const std::vector &rows) { + driver_->set_driver_mode(GenX320RoiDriver::DriverMode::LATCH); + return driver_->set_lines(cols, rows); +} + +bool GenX320RoiInterface::set_windows_impl(const std::vector &windows) { + driver_->set_driver_mode(GenX320RoiDriver::DriverMode::MASTER); + return driver_->set_windows(windows); +} + +std::vector GenX320RoiInterface::get_windows() const { + return driver_->get_windows(); +} + +} // namespace Metavision diff --git a/hal_psee_plugins/src/devices/genx320/genx320_roi_pixel_mask_interface.cpp b/hal_psee_plugins/src/devices/genx320/genx320_roi_pixel_mask_interface.cpp new file mode 100644 index 000000000..883629b04 --- /dev/null +++ b/hal_psee_plugins/src/devices/genx320/genx320_roi_pixel_mask_interface.cpp @@ -0,0 +1,57 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#include "metavision/psee_hw_layer/devices/genx320/genx320_roi_pixel_mask_interface.h" + +namespace Metavision { + +GenX320RoiPixelMaskInterface::GenX320RoiPixelMaskInterface(const std::shared_ptr &driver) : + driver_(driver) {} + +bool GenX320RoiPixelMaskInterface::set_pixel(const unsigned int &column, const unsigned int &row, const bool &enable) { + return driver_->set_pixel(column, row, enable); +} + +std::vector> GenX320RoiPixelMaskInterface::get_pixels() const { + std::vector> pixel_list; + + GenX320RoiDriver::Grid grid = driver_->get_grid(); + auto grid_size = grid.get_size(); + auto x_max = std::get<0>(grid_size); + auto y_max = std::get<1>(grid_size); + + for (unsigned int y = 0; y < y_max; y++) { + for (unsigned int x = 0; x < x_max; x++) { + uint32_t vector = grid.get_vector(x, y); + for (unsigned int i = 0; i < 32; i++) { + auto valid = (1 << i) & vector; + if (!valid) { + pixel_list.push_back(std::make_pair(x * 32 + i, y)); + } + } + } + } + + return pixel_list; +} + +void GenX320RoiPixelMaskInterface::apply_pixels() { + driver_->set_driver_mode(GenX320RoiDriver::DriverMode::LATCH); + driver_->enable(true); +} + +void GenX320RoiPixelMaskInterface::reset_pixels() { + GenX320RoiDriver::Grid default_grid(10, 320); + driver_->set_grid(default_grid); + driver_->reset_to_full_roi(); +} + +} // namespace Metavision \ No newline at end of file diff --git a/hal_psee_plugins/src/devices/imx636/imx636_tz_device.cpp b/hal_psee_plugins/src/devices/imx636/imx636_tz_device.cpp index 0866bf00e..75f343f51 100644 --- a/hal_psee_plugins/src/devices/imx636/imx636_tz_device.cpp +++ b/hal_psee_plugins/src/devices/imx636/imx636_tz_device.cpp @@ -240,7 +240,7 @@ int TzImx636::get_pixel_dead_time() { int max_retries = 10; while (reg["refr_valid"].read_value() == 0) { if (max_retries == 0) { - throw HalException(HalErrorCode::MaximumRetriesExeeded); + throw HalException(HalErrorCode::MaximumRetriesExceeded); } max_retries--; } diff --git a/hal_psee_plugins/src/devices/imx646/imx646_tz_device.cpp b/hal_psee_plugins/src/devices/imx646/imx646_tz_device.cpp index d0a74622c..99700d7c7 100644 --- a/hal_psee_plugins/src/devices/imx646/imx646_tz_device.cpp +++ b/hal_psee_plugins/src/devices/imx646/imx646_tz_device.cpp @@ -247,7 +247,7 @@ int TzImx646::get_pixel_dead_time() { int max_retries = 10; while (reg["refr_valid"].read_value() == 0) { if (max_retries == 0) { - throw HalException(HalErrorCode::MaximumRetriesExeeded); + throw HalException(HalErrorCode::MaximumRetriesExceeded); } max_retries--; } diff --git a/hal_psee_plugins/src/devices/psee-video/tz_psee_video_build.cpp b/hal_psee_plugins/src/devices/psee-video/tz_psee_video_build.cpp index 2df7ca2d4..fae02eeb2 100644 --- a/hal_psee_plugins/src/devices/psee-video/tz_psee_video_build.cpp +++ b/hal_psee_plugins/src/devices/psee-video/tz_psee_video_build.cpp @@ -27,6 +27,7 @@ std::shared_ptr TzPseeVideo::build(std::shared_ptr namespace Metavision { @@ -24,7 +25,9 @@ TzIssdDevice::TzIssdDevice(const Issd &issd) : issd(issd) { } TzIssdDevice::~TzIssdDevice() { - destroy(); + try { + destroy(); + } catch (...) { MV_HAL_LOG_WARNING() << "Treuzell ISSD Device destruction failed!"; } } void TzIssdDevice::initialize() { diff --git a/hal_psee_plugins/src/facilities/psee_roi.cpp b/hal_psee_plugins/src/facilities/psee_roi.cpp index f172d4ce2..86e553a1a 100644 --- a/hal_psee_plugins/src/facilities/psee_roi.cpp +++ b/hal_psee_plugins/src/facilities/psee_roi.cpp @@ -55,16 +55,28 @@ bool PseeROI::set_mode(const Mode &mode) { return mode == Mode::ROI; } +I_ROI::Mode PseeROI::get_mode() const { + return Mode::ROI; +} + size_t PseeROI::get_max_supported_windows_count() const { return 1; } bool PseeROI::set_windows_impl(const std::vector &windows) { - return set_ROIs_from_bitword(create_ROIs(windows), true); + if (set_ROIs_from_bitword(create_ROIs(windows), false)) { + active_windows_ = windows; + return true; + } + return false; +} + +std::vector PseeROI::get_windows() const { + return active_windows_; } bool PseeROI::set_ROIs_from_bitword(const std::vector &vroiparams, bool is_enabled) { - program_ROI_Helper(vroiparams, is_enabled); + write_ROI(vroiparams); return true; } @@ -72,7 +84,7 @@ bool PseeROI::set_lines(const std::vector &cols, const std::vector & if ((cols.size() != static_cast(device_width_)) || (rows.size() != static_cast(device_height_))) { return false; } - program_ROI_Helper(create_ROIs(cols, rows), true); + write_ROI(create_ROIs(cols, rows)); return true; } @@ -167,6 +179,7 @@ std::vector PseeROI::create_ROIs(const std::vector &cols_to_enab } } + active_windows_ = windows; return create_ROIs(windows, device_width_, device_height_, roi_x_flipped(), get_word_size(), x_offset, y_offset); } @@ -182,9 +195,4 @@ int PseeROI::get_word_size() const { return 32; } -void PseeROI::program_ROI_Helper(const std::vector &vroiparams, bool is_enabled) { - write_ROI(vroiparams); - enable(is_enabled); -} - } // namespace Metavision diff --git a/hal_psee_plugins/src/utils/make_decoder.cpp b/hal_psee_plugins/src/utils/make_decoder.cpp index 802873164..9f8cf16fa 100644 --- a/hal_psee_plugins/src/utils/make_decoder.cpp +++ b/hal_psee_plugins/src/utils/make_decoder.cpp @@ -17,11 +17,14 @@ #include "metavision/hal/utils/device_builder.h" #include "metavision/hal/facilities/i_event_decoder.h" +#include "metavision/hal/facilities/i_event_frame_decoder.h" +#include "metavision/hal/facilities/i_events_stream_decoder.h" #include "metavision/hal/decoders/aer/aer_decoder.h" #include "metavision/hal/decoders/evt2/evt2_decoder.h" #include "metavision/hal/decoders/evt21/evt21_decoder.h" #include "metavision/hal/decoders/evt3/evt3_decoder.h" #include "metavision/hal/decoders/ehc/ehc_decoder.h" +#include "metavision/hal/decoders/mtr/mtr_decoder.h" #include "metavision/hal/utils/hal_log.h" #include "metavision/psee_hw_layer/utils/psee_format.h" @@ -60,9 +63,11 @@ static std::pair get_pixel_layout(const std::string &layout_ std::shared_ptr make_decoder(DeviceBuilder &device_builder, const StreamFormat &format, size_t &raw_size_bytes, bool do_time_shifting) { std::shared_ptr decoder; + std::shared_ptr frame_decoder; + auto i_geometry = device_builder.add_facility(format.geometry()); + raw_size_bytes = 0; if (format.name() == "EVT3") { - auto i_geometry = device_builder.add_facility(format.geometry()); auto cd_decoder = device_builder.add_facility(std::make_unique>()); auto ext_trig_decoder = device_builder.add_facility(std::make_unique>()); auto erc_count_ev_decoder = device_builder.add_facility(std::make_unique>()); @@ -73,7 +78,6 @@ std::shared_ptr make_decoder(DeviceBuilder &device_builde raw_size_bytes = decoder->get_raw_event_size_bytes(); } else if (format.name() == "EVT2") { - auto i_geometry = device_builder.add_facility(format.geometry()); auto cd_decoder = device_builder.add_facility(std::make_unique>()); auto ext_trig_decoder = device_builder.add_facility(std::make_unique>()); @@ -81,7 +85,6 @@ std::shared_ptr make_decoder(DeviceBuilder &device_builde device_builder.add_facility(std::make_unique(do_time_shifting, cd_decoder, ext_trig_decoder)); raw_size_bytes = decoder->get_raw_event_size_bytes(); } else if (format.name() == "EVT21") { - auto i_geometry = device_builder.add_facility(format.geometry()); auto cd_decoder = device_builder.add_facility(std::make_unique>()); auto ext_trig_decoder = device_builder.add_facility(std::make_unique>()); auto erc_count_ev_decoder = device_builder.add_facility(std::make_unique>()); @@ -96,7 +99,6 @@ std::shared_ptr make_decoder(DeviceBuilder &device_builde } raw_size_bytes = decoder->get_raw_event_size_bytes(); } else if (format.name() == "HISTO3D") { - auto i_geometry = device_builder.add_facility(format.geometry()); auto pixel_layout = get_pixel_layout(format["pixellayout"]); int pixel_bytes; try { @@ -108,27 +110,32 @@ std::shared_ptr make_decoder(DeviceBuilder &device_builde // stoi throws non standard exceptions on Android throw std::invalid_argument("Format is missing a valid pixelbytes value"); } - auto histo_decoder = device_builder.add_facility( + frame_decoder = device_builder.add_facility( std::make_unique(i_geometry->get_height(), i_geometry->get_width(), pixel_layout.first, pixel_layout.second, pixel_bytes == 2)); - raw_size_bytes = histo_decoder->get_raw_event_size_bytes(); + raw_size_bytes = frame_decoder->get_raw_event_size_bytes(); } else if (format.name() == "DIFF3D") { auto pixel_layout = get_pixel_layout(format["pixellayout"]); - auto i_geometry = device_builder.add_facility(format.geometry()); - auto diff_decoder = device_builder.add_facility( + frame_decoder = device_builder.add_facility( std::make_unique(i_geometry->get_height(), i_geometry->get_width(), pixel_layout.first)); - raw_size_bytes = diff_decoder->get_raw_event_size_bytes(); + raw_size_bytes = frame_decoder->get_raw_event_size_bytes(); } else if (format.name() == "AER-8b") { - auto i_geometry = device_builder.add_facility(format.geometry()); auto cd_decoder = device_builder.add_facility(std::make_unique>()); decoder = device_builder.add_facility(std::make_unique>(do_time_shifting, cd_decoder)); raw_size_bytes = decoder->get_raw_event_size_bytes(); } else if (format.name() == "AER-4b") { - auto i_geometry = device_builder.add_facility(format.geometry()); auto cd_decoder = device_builder.add_facility(std::make_unique>()); decoder = device_builder.add_facility(std::make_unique>(do_time_shifting, cd_decoder)); raw_size_bytes = decoder->get_raw_event_size_bytes(); - } else { + } else if (format.name().rfind("MTR") == 0) { + auto mtr_decoder = mtr_decoder_from_format(*i_geometry, format.name()); + if (mtr_decoder) { + frame_decoder = device_builder.add_facility(std::move(mtr_decoder)); + raw_size_bytes = frame_decoder->get_raw_event_size_bytes(); + } + } + + if (!decoder && !frame_decoder) { throw std::runtime_error("Format " + format.name() + " is not supported"); } diff --git a/hal_psee_plugins/src/utils/tz_device_control.cpp b/hal_psee_plugins/src/utils/tz_device_control.cpp index 184105da2..8dda1022d 100644 --- a/hal_psee_plugins/src/utils/tz_device_control.cpp +++ b/hal_psee_plugins/src/utils/tz_device_control.cpp @@ -38,7 +38,11 @@ TzDeviceControl::TzDeviceControl(std::vector> &devices TzDeviceControl::~TzDeviceControl() { // Stop streaming if the caller program "forgot" if (streaming_) { - stop(); + try { + stop(); + } catch (const std::system_error &e) { + MV_HAL_LOG_WARNING() << "Treuzell Device Control destruction failed: " << e.what(); + } } // Stop intermediate blocks for (auto dev = devices_.rbegin(); dev != devices_.rend(); dev++) { diff --git a/hal_psee_plugins/test/device_discovery_psee_plugins_gtest.cpp b/hal_psee_plugins/test/device_discovery_psee_plugins_gtest.cpp index cc2124a6b..36dff70e0 100644 --- a/hal_psee_plugins/test/device_discovery_psee_plugins_gtest.cpp +++ b/hal_psee_plugins/test/device_discovery_psee_plugins_gtest.cpp @@ -28,7 +28,7 @@ #include "metavision/hal/facilities/i_trigger_in.h" #include "metavision/hal/facilities/i_trigger_out.h" #include "metavision/hal/facilities/i_ll_biases.h" -#include "metavision/hal/facilities/i_event_rate_noise_filter_module.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" #include "metavision/hal/facilities/i_events_stream_decoder.h" #include "metavision/hal/facilities/i_event_decoder.h" #include "metavision/hal/facilities/i_hw_register.h" @@ -575,7 +575,7 @@ TEST_WITH_CAMERA(DeviceDiscoveryRepositoryNoF_GTest, open_camera_build_gen31, // Now check the information on the device ASSERT_NE(nullptr, device->get_facility()); ASSERT_NE(nullptr, device->get_facility()); - ASSERT_NE(nullptr, device->get_facility()); + ASSERT_NE(nullptr, device->get_facility()); ASSERT_EQ(VGAGeometry::width_, geometry->get_width()); ASSERT_EQ(VGAGeometry::height_, geometry->get_height()); if (hw_id_->get_system_id() == 0x28) { diff --git a/hal_psee_plugins/test/gen31_event_rate_noise_filter_module_gtest.cpp b/hal_psee_plugins/test/gen31_event_rate_noise_filter_module_gtest.cpp index 1c7a3d5ac..878c5666a 100644 --- a/hal_psee_plugins/test/gen31_event_rate_noise_filter_module_gtest.cpp +++ b/hal_psee_plugins/test/gen31_event_rate_noise_filter_module_gtest.cpp @@ -19,7 +19,7 @@ #include "metavision/hal/device/device.h" #include "metavision/hal/utils/hal_exception.h" #include "metavision/hal/facilities/i_hw_identification.h" -#include "metavision/hal/facilities/i_event_rate_noise_filter_module.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" #include "metavision/hal/facilities/i_events_stream.h" #include "metavision/hal/decoders/base/event_base.h" #include "metavision/hal/decoders/evt2/evt2_event_types.h" @@ -45,13 +45,13 @@ class Gen31EventRateNoiseFilterModule_GTest : public ::testing::Test { ASSERT_NE(nullptr, device_.get()); - ev_rate_ = device_->get_facility(); + ev_rate_ = device_->get_facility(); ASSERT_NE(nullptr, ev_rate_); } protected: std::unique_ptr device_; - I_EventRateNoiseFilterModule *ev_rate_{nullptr}; + I_EventRateActivityFilterModule *ev_rate_{nullptr}; static constexpr uint32_t min_event_rate_threshold_kev_s_ = Gen31_EventRateNoiseFilterModule::min_event_rate_threshold_kev_s; diff --git a/hal_psee_plugins/test/psee_raw_file_decoder_gtest.cpp b/hal_psee_plugins/test/psee_raw_file_decoder_gtest.cpp index e308efd08..e2c8ed6ac 100644 --- a/hal_psee_plugins/test/psee_raw_file_decoder_gtest.cpp +++ b/hal_psee_plugins/test/psee_raw_file_decoder_gtest.cpp @@ -18,6 +18,7 @@ #include "metavision/utils/gtest/gtest_with_tmp_dir.h" #include "metavision/utils/gtest/gtest_custom.h" #include "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/base/events/event_pointcloud.h" #include "metavision/sdk/base/events/raw_event_frame_diff.h" #include "metavision/sdk/base/events/raw_event_frame_histo.h" #include "metavision/sdk/base/utils/get_time.h" @@ -1310,3 +1311,79 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_byte_by_byte) { // THEN We decode the same data CD & triggers that are encoded in the RAW file ASSERT_EQ(31300, received_cd_event_count); } + +TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_mtr_nominal) { + // GIVEN a RAW file in MTR format with a known content + std::string dataset_file_path = + (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "0101_cm_mtr12_output.raw") + .string(); + + size_t received_event_frame_count = 0; + RawFileConfig cfg; + cfg.do_time_shifting_ = false; + std::unique_ptr device(DeviceDiscovery::open_raw_file(dataset_file_path, cfg)); + + if (!device) { + std::cerr << "Failed to open raw file." << std::endl; + FAIL(); + } + + // AND a PSEE MTR decoder + auto mtr_decoder = device->get_facility>(); + auto es = device->get_facility(); + + ASSERT_NE(nullptr, mtr_decoder); + ASSERT_NE(nullptr, es); + + mtr_decoder->add_event_frame_callback([&](auto pointcloud) { received_event_frame_count++; }); + + es->start(); + + // WHEN we stream and decode the events in the file + long int bytes_polled_count; + while (es->wait_next_buffer() >= 0) { + auto raw_buffer = es->get_latest_raw_data(bytes_polled_count); + mtr_decoder->decode(raw_buffer, raw_buffer + bytes_polled_count); + } + + // THEN We decode the same MTR data that are encoded in the RAW file + ASSERT_EQ(378, received_event_frame_count); +} + +TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_mtru_nominal) { + // GIVEN a RAW file in MTRU format with a known content + std::string dataset_file_path = + (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "0101_cm_mtru_output.raw") + .string(); + + size_t received_event_frame_count = 0; + RawFileConfig cfg; + cfg.do_time_shifting_ = false; + std::unique_ptr device(DeviceDiscovery::open_raw_file(dataset_file_path, cfg)); + + if (!device) { + std::cerr << "Failed to open raw file." << std::endl; + FAIL(); + } + + // AND a PSEE MTR decoder + auto mtr_decoder = device->get_facility>(); + auto es = device->get_facility(); + + ASSERT_NE(nullptr, mtr_decoder); + ASSERT_NE(nullptr, es); + + mtr_decoder->add_event_frame_callback([&](auto pointcloud) { received_event_frame_count++; }); + + es->start(); + + // WHEN we stream and decode the events in the file + long int bytes_polled_count; + while (es->wait_next_buffer() >= 0) { + auto raw_buffer = es->get_latest_raw_data(bytes_polled_count); + mtr_decoder->decode(raw_buffer, raw_buffer + bytes_polled_count); + } + + // THEN We decode the same MTR data that are encoded in the RAW file + ASSERT_EQ(378, received_event_frame_count); +} diff --git a/sdk/modules/base/cpp/CMakeLists.txt b/sdk/modules/base/cpp/CMakeLists.txt index 8c3272fba..60fcf3bbd 100644 --- a/sdk/modules/base/cpp/CMakeLists.txt +++ b/sdk/modules/base/cpp/CMakeLists.txt @@ -13,8 +13,8 @@ add_subdirectory(lib) # Add sources to the library add_subdirectory(src) -# Apps -add_subdirectory(apps) +# Samples +add_subdirectory(samples) # Documentations if (GENERATE_DOC) diff --git a/sdk/modules/base/cpp/include/metavision/sdk/base/events/event_pointcloud.h b/sdk/modules/base/cpp/include/metavision/sdk/base/events/event_pointcloud.h new file mode 100644 index 000000000..977988dce --- /dev/null +++ b/sdk/modules/base/cpp/include/metavision/sdk/base/events/event_pointcloud.h @@ -0,0 +1,40 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_BASE_EVENT_POINTCLOUD_H +#define METAVISION_SDK_BASE_EVENT_POINTCLOUD_H + +#include + +namespace Metavision { + +/// @brief Class representing a point cloud frame of 3D events +class PointCloud { +public: + /// @brief Class representing a 3D point: + class Point3D { + public: + float X, Y, Z; // 3d coordinates of reprojected point + int channel_id; // channel number + int line_id; // repetition number + }; + + /// @brief Frame number + unsigned int frame_id; + /// @brief Maximum depth within the frame + float max_depth; + /// @brief List of 3D events + std::vector points; +}; + +} // namespace Metavision + +#endif /* METAVISION_SDK_BASE_EVENT_POINTCLOUD_H */ diff --git a/sdk/modules/base/cpp/apps/CMakeLists.txt b/sdk/modules/base/cpp/samples/CMakeLists.txt similarity index 100% rename from sdk/modules/base/cpp/apps/CMakeLists.txt rename to sdk/modules/base/cpp/samples/CMakeLists.txt diff --git a/sdk/modules/base/cpp/apps/metavision_software_info/CMakeLists.txt b/sdk/modules/base/cpp/samples/metavision_software_info/CMakeLists.txt similarity index 87% rename from sdk/modules/base/cpp/apps/metavision_software_info/CMakeLists.txt rename to sdk/modules/base/cpp/samples/metavision_software_info/CMakeLists.txt index 0e18542ab..d152b9c84 100644 --- a/sdk/modules/base/cpp/apps/metavision_software_info/CMakeLists.txt +++ b/sdk/modules/base/cpp/samples/metavision_software_info/CMakeLists.txt @@ -16,13 +16,13 @@ install(TARGETS metavision_software_info ) install(FILES metavision_software_info.cpp - DESTINATION share/metavision/sdk/base/apps/metavision_software_info + DESTINATION share/metavision/sdk/base/cpp_samples/metavision_software_info COMPONENT metavision-sdk-base-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/base/apps/metavision_software_info + DESTINATION share/metavision/sdk/base/cpp_samples/metavision_software_info COMPONENT metavision-sdk-base-samples ) diff --git a/sdk/modules/base/cpp/apps/metavision_software_info/CMakeLists.txt.install b/sdk/modules/base/cpp/samples/metavision_software_info/CMakeLists.txt.install similarity index 100% rename from sdk/modules/base/cpp/apps/metavision_software_info/CMakeLists.txt.install rename to sdk/modules/base/cpp/samples/metavision_software_info/CMakeLists.txt.install diff --git a/sdk/modules/base/cpp/apps/metavision_software_info/metavision_software_info.cpp b/sdk/modules/base/cpp/samples/metavision_software_info/metavision_software_info.cpp similarity index 100% rename from sdk/modules/base/cpp/apps/metavision_software_info/metavision_software_info.cpp rename to sdk/modules/base/cpp/samples/metavision_software_info/metavision_software_info.cpp diff --git a/sdk/modules/base/cpp/apps/metavision_software_info/test/CMakeLists.txt b/sdk/modules/base/cpp/samples/metavision_software_info/test/CMakeLists.txt similarity index 100% rename from sdk/modules/base/cpp/apps/metavision_software_info/test/CMakeLists.txt rename to sdk/modules/base/cpp/samples/metavision_software_info/test/CMakeLists.txt diff --git a/sdk/modules/base/cpp/apps/metavision_software_info/test/metavision_software_info_pytest.py.in b/sdk/modules/base/cpp/samples/metavision_software_info/test/metavision_software_info_pytest.py.in similarity index 100% rename from sdk/modules/base/cpp/apps/metavision_software_info/test/metavision_software_info_pytest.py.in rename to sdk/modules/base/cpp/samples/metavision_software_info/test/metavision_software_info_pytest.py.in diff --git a/sdk/modules/core/cpp/CMakeLists.txt b/sdk/modules/core/cpp/CMakeLists.txt index 37bebe900..020186d7d 100644 --- a/sdk/modules/core/cpp/CMakeLists.txt +++ b/sdk/modules/core/cpp/CMakeLists.txt @@ -10,8 +10,7 @@ # Add library add_subdirectory(lib) -# Samples and apps -add_subdirectory(apps) +# Samples add_subdirectory(samples) # Add sources to the library diff --git a/sdk/modules/core/cpp/apps/CMakeLists.txt b/sdk/modules/core/cpp/apps/CMakeLists.txt deleted file mode 100644 index 5d462dbca..000000000 --- a/sdk/modules/core/cpp/apps/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) Prophesee S.A. -# -# 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. - -option(COMPILE_PLAYER "Compile Metavision SDK player" ON) -if (COMPILE_PLAYER) - add_subdirectory(metavision_player) -endif () -add_subdirectory(metavision_file_to_video) \ No newline at end of file diff --git a/sdk/modules/core/cpp/samples/CMakeLists.txt b/sdk/modules/core/cpp/samples/CMakeLists.txt index daf53d17b..61c11e986 100644 --- a/sdk/modules/core/cpp/samples/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/CMakeLists.txt @@ -7,11 +7,17 @@ # 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. +option(COMPILE_PLAYER "Compile Metavision SDK player" ON) +if (COMPILE_PLAYER) + add_subdirectory(metavision_player) +endif () + if (NOT ANDROID) add_subdirectory(metavision_composed_viewer) add_subdirectory(metavision_csv_viewer) add_subdirectory(metavision_event_frame_generation) add_subdirectory(metavision_event_frame_gpu_loading) + add_subdirectory(metavision_file_to_video) add_subdirectory(metavision_filtering) add_subdirectory(metavision_sdk_get_started) add_subdirectory(metavision_time_surface) diff --git a/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt index ef513bc92..10c256684 100644 --- a/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt @@ -14,12 +14,12 @@ add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) \ No newline at end of file diff --git a/sdk/modules/core/cpp/samples/metavision_csv_viewer/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_csv_viewer/CMakeLists.txt index f52d347ce..a02a68c90 100644 --- a/sdk/modules/core/cpp/samples/metavision_csv_viewer/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_csv_viewer/CMakeLists.txt @@ -14,12 +14,12 @@ add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) \ No newline at end of file diff --git a/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt index 2cbffb9af..5492a958c 100644 --- a/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt @@ -14,12 +14,12 @@ add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) \ No newline at end of file diff --git a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt index 695fa75f9..73f3b56c9 100644 --- a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt @@ -38,12 +38,12 @@ if (CMAKE_CUDA_COMPILER) endif(CMAKE_CUDA_COMPILER) install(FILES ${source_files} ${cuda_source_files} - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) diff --git a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/metavision_event_frame_gpu_loading.cpp b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/metavision_event_frame_gpu_loading.cpp index 2015e346d..bc7da927c 100644 --- a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/metavision_event_frame_gpu_loading.cpp +++ b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/metavision_event_frame_gpu_loading.cpp @@ -9,6 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +// This code sample demonstrates how to preprocess raw event frame on a GPU using CUDA. + #include #include #include diff --git a/sdk/modules/core/cpp/apps/metavision_file_to_video/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt similarity index 88% rename from sdk/modules/core/cpp/apps/metavision_file_to_video/CMakeLists.txt rename to sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt index ad1a7a386..f807c34b2 100644 --- a/sdk/modules/core/cpp/apps/metavision_file_to_video/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt @@ -22,13 +22,13 @@ install(TARGETS metavision_file_to_video ) install(FILES metavision_file_to_video.cpp - DESTINATION share/metavision/sdk/core/apps/metavision_file_to_video + DESTINATION share/metavision/sdk/core/cpp_samples/metavision_file_to_video COMPONENT metavision-sdk-core-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/apps/metavision_file_to_video + DESTINATION share/metavision/sdk/core/cpp_samples/metavision_file_to_video COMPONENT metavision-sdk-core-samples ) diff --git a/sdk/modules/core/cpp/apps/metavision_file_to_video/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt.install similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_file_to_video/CMakeLists.txt.install rename to sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt.install diff --git a/sdk/modules/core/cpp/apps/metavision_file_to_video/metavision_file_to_video.cpp b/sdk/modules/core/cpp/samples/metavision_file_to_video/metavision_file_to_video.cpp similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_file_to_video/metavision_file_to_video.cpp rename to sdk/modules/core/cpp/samples/metavision_file_to_video/metavision_file_to_video.cpp diff --git a/sdk/modules/core/cpp/apps/metavision_file_to_video/test/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_file_to_video/test/CMakeLists.txt similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_file_to_video/test/CMakeLists.txt rename to sdk/modules/core/cpp/samples/metavision_file_to_video/test/CMakeLists.txt diff --git a/sdk/modules/core/cpp/apps/metavision_file_to_video/test/metavision_file_to_video_pytest.py b/sdk/modules/core/cpp/samples/metavision_file_to_video/test/metavision_file_to_video_pytest.py similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_file_to_video/test/metavision_file_to_video_pytest.py rename to sdk/modules/core/cpp/samples/metavision_file_to_video/test/metavision_file_to_video_pytest.py diff --git a/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt index d58ec3678..e2644c58f 100644 --- a/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt @@ -14,12 +14,12 @@ add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) \ No newline at end of file diff --git a/sdk/modules/core/cpp/apps/metavision_player/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt similarity index 89% rename from sdk/modules/core/cpp/apps/metavision_player/CMakeLists.txt rename to sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt index d48cd25c7..e0d6b0df4 100644 --- a/sdk/modules/core/cpp/apps/metavision_player/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt @@ -33,11 +33,11 @@ install( # Install source code install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/apps/metavision_player + DESTINATION share/metavision/sdk/core/cpp_samples/metavision_player COMPONENT metavision-sdk-core-samples ) install(DIRECTORY inc src - DESTINATION share/metavision/sdk/core/apps/metavision_player + DESTINATION share/metavision/sdk/core/cpp_samples/metavision_player COMPONENT metavision-sdk-core-samples ) diff --git a/sdk/modules/core/cpp/apps/metavision_player/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt.install similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/CMakeLists.txt.install rename to sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt.install diff --git a/sdk/modules/core/cpp/apps/metavision_player/inc/analysis_utils.h b/sdk/modules/core/cpp/samples/metavision_player/inc/analysis_utils.h similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/inc/analysis_utils.h rename to sdk/modules/core/cpp/samples/metavision_player/inc/analysis_utils.h diff --git a/sdk/modules/core/cpp/apps/metavision_player/inc/analysis_view.h b/sdk/modules/core/cpp/samples/metavision_player/inc/analysis_view.h similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/inc/analysis_view.h rename to sdk/modules/core/cpp/samples/metavision_player/inc/analysis_view.h diff --git a/sdk/modules/core/cpp/apps/metavision_player/inc/camera_view.h b/sdk/modules/core/cpp/samples/metavision_player/inc/camera_view.h similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/inc/camera_view.h rename to sdk/modules/core/cpp/samples/metavision_player/inc/camera_view.h diff --git a/sdk/modules/core/cpp/apps/metavision_player/inc/params.h b/sdk/modules/core/cpp/samples/metavision_player/inc/params.h similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/inc/params.h rename to sdk/modules/core/cpp/samples/metavision_player/inc/params.h diff --git a/sdk/modules/core/cpp/apps/metavision_player/inc/utils.h b/sdk/modules/core/cpp/samples/metavision_player/inc/utils.h similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/inc/utils.h rename to sdk/modules/core/cpp/samples/metavision_player/inc/utils.h diff --git a/sdk/modules/core/cpp/apps/metavision_player/inc/view.h b/sdk/modules/core/cpp/samples/metavision_player/inc/view.h similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/inc/view.h rename to sdk/modules/core/cpp/samples/metavision_player/inc/view.h diff --git a/sdk/modules/core/cpp/apps/metavision_player/inc/viewer.h b/sdk/modules/core/cpp/samples/metavision_player/inc/viewer.h similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/inc/viewer.h rename to sdk/modules/core/cpp/samples/metavision_player/inc/viewer.h diff --git a/sdk/modules/core/cpp/apps/metavision_player/src/analysis_view.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/analysis_view.cpp similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/src/analysis_view.cpp rename to sdk/modules/core/cpp/samples/metavision_player/src/analysis_view.cpp diff --git a/sdk/modules/core/cpp/apps/metavision_player/src/camera_view.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/camera_view.cpp similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/src/camera_view.cpp rename to sdk/modules/core/cpp/samples/metavision_player/src/camera_view.cpp diff --git a/sdk/modules/core/cpp/apps/metavision_player/src/main.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/main.cpp similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/src/main.cpp rename to sdk/modules/core/cpp/samples/metavision_player/src/main.cpp diff --git a/sdk/modules/core/cpp/apps/metavision_player/src/view.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/view.cpp similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/src/view.cpp rename to sdk/modules/core/cpp/samples/metavision_player/src/view.cpp diff --git a/sdk/modules/core/cpp/apps/metavision_player/src/viewer.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/viewer.cpp similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/src/viewer.cpp rename to sdk/modules/core/cpp/samples/metavision_player/src/viewer.cpp diff --git a/sdk/modules/core/cpp/apps/metavision_player/test/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_player/test/CMakeLists.txt similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/test/CMakeLists.txt rename to sdk/modules/core/cpp/samples/metavision_player/test/CMakeLists.txt diff --git a/sdk/modules/core/cpp/apps/metavision_player/test/player_gtest.cpp b/sdk/modules/core/cpp/samples/metavision_player/test/player_gtest.cpp similarity index 100% rename from sdk/modules/core/cpp/apps/metavision_player/test/player_gtest.cpp rename to sdk/modules/core/cpp/samples/metavision_player/test/player_gtest.cpp diff --git a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt index a103d3b70..5fcc1a2c9 100644 --- a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt @@ -14,12 +14,12 @@ add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) \ No newline at end of file diff --git a/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt index 1d76afb85..e29a22514 100644 --- a/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt @@ -14,12 +14,12 @@ add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/samples/${sample} + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} COMPONENT metavision-sdk-core-samples ) diff --git a/sdk/modules/core/cpp/samples/metavision_time_surface/metavision_time_surface.cpp b/sdk/modules/core/cpp/samples/metavision_time_surface/metavision_time_surface.cpp index c7bd1d834..59b3cbef1 100644 --- a/sdk/modules/core/cpp/samples/metavision_time_surface/metavision_time_surface.cpp +++ b/sdk/modules/core/cpp/samples/metavision_time_surface/metavision_time_surface.cpp @@ -25,6 +25,7 @@ int main(int argc, char *argv[]) { std::string serial; std::string biases_file; std::string in_file_path; + uint32_t delta_ts; const std::string short_program_desc( "Example of using Metavision SDK Core API for visualizing Time Surface of events.\n"); @@ -36,6 +37,7 @@ int main(int argc, char *argv[]) { ("serial,s", po::value(&serial),"Serial ID of the camera. This flag is incompatible with flag '--input-file'.") ("input-file,i", po::value(&in_file_path), "Path to input file. If not specified, the camera live stream is used.") ("biases,b", po::value(&biases_file), "Path to a biases file. If not specified, the camera will be configured with the default biases.") + ("accumulation-time,a", po::value(&delta_ts)->default_value(10000), "Accumulation time for which to display the Time Surface.") ; // clang-format on @@ -137,7 +139,7 @@ int main(int argc, char *argv[]) { if (!time_surface.empty()) { std::unique_lock lock(frame_mutex); // generate the time surface from MostRecentTimestampBuffer - time_surface.generate_img_time_surface(last_time, 10000, time_surface_gray); + time_surface.generate_img_time_surface(last_time, delta_ts, time_surface_gray); // apply a colormap to the time surface and display the new frame cv::applyColorMap(time_surface_gray, heatmap, cv::COLORMAP_JET); window.show(heatmap); diff --git a/sdk/modules/core/python/tests/CMakeLists.txt b/sdk/modules/core/python/tests/CMakeLists.txt index 7cde6673e..5bdfe500d 100644 --- a/sdk/modules/core/python/tests/CMakeLists.txt +++ b/sdk/modules/core/python/tests/CMakeLists.txt @@ -7,14 +7,14 @@ # 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. -lfs_download("datasets/openeb/core/event_io/csv_zip_eth") -lfs_download("datasets/openeb/blinking_gen4_with_ext_triggers.raw") -lfs_download("datasets/openeb/diff3d.raw") -lfs_download("datasets/openeb/histo3d.raw") -lfs_download("datasets/openeb/histo3d_padding.raw") -lfs_download("datasets/openeb/events_big_time_gap_repeated_ts.raw") -lfs_download("datasets/openeb/events_big_time_gap_repeated_ts.dat") -lfs_download("datasets/openeb/ts_offset_test.hdf5") +lfs_download("datasets/openeb/core/event_io/csv_zip_eth" VALIDATION) +lfs_download("datasets/openeb/blinking_gen4_with_ext_triggers.raw" VALIDATION) +lfs_download("datasets/openeb/diff3d.raw" VALIDATION) +lfs_download("datasets/openeb/histo3d.raw" VALIDATION) +lfs_download("datasets/openeb/histo3d_padding.raw" VALIDATION) +lfs_download("datasets/openeb/events_big_time_gap_repeated_ts.raw" VALIDATION) +lfs_download("datasets/openeb/events_big_time_gap_repeated_ts.dat" VALIDATION) +lfs_download("datasets/openeb/ts_offset_test.hdf5" VALIDATION) add_sdk_python_module_test(core) diff --git a/sdk/modules/core_ml/python/CMakeLists.txt b/sdk/modules/core_ml/python/CMakeLists.txt index f55b9f98c..af924e6a6 100644 --- a/sdk/modules/core_ml/python/CMakeLists.txt +++ b/sdk/modules/core_ml/python/CMakeLists.txt @@ -11,7 +11,8 @@ add_cpack_component(PUBLIC metavision-sdk-core-ml-python metavision-sdk-core-ml-python-samples) # Models -lfs_download("sdk/modules/core_ml/python/models") +lfs_download("sdk/modules/core_ml/python/models" COMPILATION) +lfs_download("sdk/modules/core_ml/python/models" VALIDATION) # Add Python library add_subdirectory(pypkg) diff --git a/sdk/modules/core_ml/python/tests/CMakeLists.txt b/sdk/modules/core_ml/python/tests/CMakeLists.txt index 5d40ef3ea..825053674 100644 --- a/sdk/modules/core_ml/python/tests/CMakeLists.txt +++ b/sdk/modules/core_ml/python/tests/CMakeLists.txt @@ -7,8 +7,8 @@ # 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. -lfs_download("datasets/openeb/core_ml") -lfs_download("sdk/modules/core_ml/python/models/corner_detection_10_heatmaps.ckpt") +lfs_download("datasets/openeb/core_ml" VALIDATION) +lfs_download("sdk/modules/core_ml/python/models/corner_detection_10_heatmaps.ckpt" VALIDATION) get_filename_component(CORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../core/python/pypkg" ABSOLUTE) get_filename_component(CORE_ML_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../pypkg" ABSOLUTE) diff --git a/sdk/modules/core_ml/python/tests/demo_corner_detection_pytest.py b/sdk/modules/core_ml/python/tests/demo_corner_detection_pytest.py index 2d0b3f3d6..17591cbe7 100644 --- a/sdk/modules/core_ml/python/tests/demo_corner_detection_pytest.py +++ b/sdk/modules/core_ml/python/tests/demo_corner_detection_pytest.py @@ -20,7 +20,7 @@ def pytestcase_demo_corner_detection(tmpdir, dataset_dir): """ video_path = os.path.join(tmpdir, "demo_video.avi") datfile = os.path.join(dataset_dir, "openeb/core_ml/corner_detection/guernica_small_for_pytest.dat") - + models_dir = os.path.join(dataset_dir, '..', 'sdk', 'modules', 'core_ml', 'python', 'models') checkpoint = os.path.join(models_dir, "corner_detection_10_heatmaps.ckpt") @@ -40,4 +40,4 @@ def pytestcase_demo_corner_detection(tmpdir, dataset_dir): env=os.environ.copy()) assert os.path.exists(video_path) - assert os.path.exists(video_path.replace("avi", "csv")) + assert os.path.exists(video_path.replace(".avi", ".csv")) diff --git a/sdk/modules/driver/cmake/MetavisionSDK_driverCPackConfig.cmake b/sdk/modules/driver/cmake/MetavisionSDK_driverCPackConfig.cmake index 16997aafb..c1ba3a45a 100644 --- a/sdk/modules/driver/cmake/MetavisionSDK_driverCPackConfig.cmake +++ b/sdk/modules/driver/cmake/MetavisionSDK_driverCPackConfig.cmake @@ -26,7 +26,7 @@ string(REPLACE ";" ", " CPACK_DEBIAN_METAVISION-SDK-DRIVER-LIB_PACKAGE_DEPENDS " # Runtime (apps) set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-BIN_DESCRIPTION "Binaries for the Metavision SDK Driver applications.\n${OPEN_PACKAGE_LICENSE}") -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-BIN_DEPENDS metavision-sdk-driver-lib metavision-sdk-core-lib) +set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-BIN_DEPENDS metavision-sdk-driver-lib metavision-sdk-core-lib metavision-hal-prophesee-hw-layer-lib) # Development package set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-DEV_DESCRIPTION "Development (C++) files for Metavision SDK Driver library.\n${OPEN_PACKAGE_LICENSE}") diff --git a/sdk/modules/driver/cpp/CMakeLists.txt b/sdk/modules/driver/cpp/CMakeLists.txt index 961264ff0..0d8740392 100644 --- a/sdk/modules/driver/cpp/CMakeLists.txt +++ b/sdk/modules/driver/cpp/CMakeLists.txt @@ -19,7 +19,6 @@ add_subdirectory(lib) add_subdirectory(src) # Apps and samples -add_subdirectory(apps) add_subdirectory(samples) # Documentations diff --git a/sdk/modules/driver/cpp/apps/CMakeLists.txt b/sdk/modules/driver/cpp/apps/CMakeLists.txt deleted file mode 100644 index 8be826a9c..000000000 --- a/sdk/modules/driver/cpp/apps/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) Prophesee S.A. -# -# 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. - -add_subdirectory(metavision_file_cutter) -add_subdirectory(metavision_file_info) -add_subdirectory(metavision_file_to_dat) -add_subdirectory(metavision_viewer) -if (HDF5_FOUND) - add_subdirectory(metavision_file_to_hdf5) -endif () -if (NOT ANDROID) - # need support for std::filesystem in NDK - add_subdirectory(metavision_active_pixel_detection) -endif (NOT ANDROID) \ No newline at end of file diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_reader.h b/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_reader.h index 0db5e7b79..29a978e98 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_reader.h +++ b/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_reader.h @@ -18,6 +18,7 @@ #include "metavision/sdk/base/events/event_cd.h" #include "metavision/sdk/base/events/event_erc_counter.h" #include "metavision/sdk/base/events/event_ext_trigger.h" +#include "metavision/sdk/base/events/event_pointcloud.h" #include "metavision/sdk/base/events/raw_event_frame_diff.h" #include "metavision/sdk/base/events/raw_event_frame_histo.h" @@ -75,6 +76,10 @@ class EventFileReader { /// @overload size_t add_read_callback(const EventFrameReadCallback &cb); + /// @brief Adds a "reading callback" called when a pointcloud has been read + /// @overload + size_t add_read_callback(const EventFrameReadCallback &cb); + /// @brief Checks if "reading callbacks" have been added /// @return true if callbacks have been added, false otherwise bool has_read_callbacks() const; @@ -137,6 +142,7 @@ class EventFileReader { void notify_events_buffer(const EventERCCounter *, const EventERCCounter *); void notify_event_frame(const RawEventFrameHisto &); void notify_event_frame(const RawEventFrameDiff &); + void notify_event_frame(const PointCloud &); void notify_seek(timestamp t); private: diff --git a/sdk/modules/driver/cpp/samples/CMakeLists.txt b/sdk/modules/driver/cpp/samples/CMakeLists.txt index 6a8b486bb..48eab4562 100644 --- a/sdk/modules/driver/cpp/samples/CMakeLists.txt +++ b/sdk/modules/driver/cpp/samples/CMakeLists.txt @@ -7,8 +7,23 @@ # 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. +add_subdirectory_if_exists(metavision_evk3d_viewer) +add_subdirectory(metavision_file_cutter) add_subdirectory(metavision_file_to_csv) +add_subdirectory(metavision_file_to_dat) +add_subdirectory(metavision_file_info) +add_subdirectory(metavision_viewer) + +if (HDF5_FOUND) + add_subdirectory(metavision_file_to_hdf5) +endif () + +if (NOT ANDROID) + # need support for std::filesystem in NDK + # AK comment here + add_subdirectory(metavision_active_pixel_detection) +endif (NOT ANDROID) if (ANDROID) add_subdirectory(metavision_viewer_android) -endif (ANDROID) \ No newline at end of file +endif (ANDROID) diff --git a/sdk/modules/driver/cpp/apps/metavision_active_pixel_detection/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt similarity index 90% rename from sdk/modules/driver/cpp/apps/metavision_active_pixel_detection/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt index b4bad9618..a85b2e8db 100644 --- a/sdk/modules/driver/cpp/apps/metavision_active_pixel_detection/CMakeLists.txt +++ b/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt @@ -20,12 +20,12 @@ install(TARGETS ${sample} ) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/driver/apps/${sample} + DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} COMPONENT metavision-sdk-driver-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/apps/${sample} + DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} COMPONENT metavision-sdk-driver-samples ) \ No newline at end of file diff --git a/sdk/modules/driver/cpp/apps/metavision_active_pixel_detection/CMakeLists.txt.install b/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt.install similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_active_pixel_detection/CMakeLists.txt.install rename to sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt.install diff --git a/sdk/modules/driver/cpp/apps/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp b/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp similarity index 97% rename from sdk/modules/driver/cpp/apps/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp rename to sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp index 26b8774cc..acf531102 100644 --- a/sdk/modules/driver/cpp/apps/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp +++ b/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp @@ -32,9 +32,11 @@ #include #include #include +#include +#include #include #include -#include +#include static const int ESCAPE = 27; static const int SPACE = 32; @@ -69,21 +71,25 @@ void onTrackbarCallback(int value, void *args) { << (ratio * 100.0) << "% )"; } +void clearROI(const Data &data) { + auto roi = data.camera->get_device().get_facility(); + roi->enable(false); +} + void applyROI(const Data &data) { bool ret = false; - auto roi_ll = data.camera->get_device().get_facility(); - if (roi_ll) { - Metavision::GenX320LowLevelRoi::Grid roi_grid(data.mask.cols / 32, data.mask.cols); + auto roi_px = data.camera->get_device().get_facility(); + if (roi_px) { if (!data.mask.empty()) { for (int y = 0; y < data.mask.rows; ++y) { const float *ptr = data.mask.ptr(y); for (int x = 0; x < data.mask.cols; ++x) { if (ptr[x] > 0.5) { - roi_grid.set_pixel(x, y, false); + roi_px->set_pixel(x, y, false); } } } - roi_ll->apply(roi_grid); + roi_px->apply_pixels(); ret = true; } } @@ -192,7 +198,7 @@ std::atomic signal_caught{false}; int main(int argc, char *argv[]) { signal(SIGINT, signalHandler); - const auto default_calib_output_path = Metavision::GenX320LowLevelRoi::default_calibration_path(); + const auto default_calib_output_path = Metavision::GenX320RoiDriver::default_calibration_path(); std::string serial; std::string biases_file_path; std::string calib_output_path; @@ -368,7 +374,10 @@ int main(int argc, char *argv[]) { camera.start(); std::vector events; + Data data(geometry.width(), geometry.height()); + data.camera = &camera; + int calib_cb_id = -1; while (!signal_caught && camera.is_running()) { { @@ -424,7 +433,7 @@ int main(int argc, char *argv[]) { data.mean = mean[0]; data.stddev = stddev[0]; data.threshold = data.mean + mult * data.stddev; - data.camera = &camera; + MV_LOG_INFO() << "Calibration done"; MV_LOG_INFO() << Metavision::Log::no_space << std::fixed << std::setw(15) << std::setprecision(2) << std::right << "Max :" << std::setw(15) << static_cast(data.max); @@ -459,6 +468,7 @@ int main(int argc, char *argv[]) { do_retry = false; break; case SPACE: { + clearROI(data); auto log = MV_LOG_INFO() << Metavision::Log::no_space; log << "\n---------------------------------------------------------------------------------------------" "-------\n"; diff --git a/sdk/modules/driver/cpp/apps/metavision_file_cutter/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt similarity index 87% rename from sdk/modules/driver/cpp/apps/metavision_file_cutter/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt index 935b5005f..ee9b9d5c6 100644 --- a/sdk/modules/driver/cpp/apps/metavision_file_cutter/CMakeLists.txt +++ b/sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt @@ -16,13 +16,13 @@ install(TARGETS metavision_file_cutter ) install(FILES metavision_file_cutter.cpp - DESTINATION share/metavision/sdk/driver/apps/metavision_file_cutter + DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_cutter COMPONENT metavision-sdk-driver-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/apps/metavision_file_cutter + DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_cutter COMPONENT metavision-sdk-driver-samples ) diff --git a/sdk/modules/driver/cpp/apps/metavision_file_cutter/CMakeLists.txt.install b/sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt.install similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_cutter/CMakeLists.txt.install rename to sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt.install diff --git a/sdk/modules/driver/cpp/apps/metavision_file_cutter/metavision_file_cutter.cpp b/sdk/modules/driver/cpp/samples/metavision_file_cutter/metavision_file_cutter.cpp similarity index 97% rename from sdk/modules/driver/cpp/apps/metavision_file_cutter/metavision_file_cutter.cpp rename to sdk/modules/driver/cpp/samples/metavision_file_cutter/metavision_file_cutter.cpp index 63c920ddf..92d6c3ea9 100644 --- a/sdk/modules/driver/cpp/apps/metavision_file_cutter/metavision_file_cutter.cpp +++ b/sdk/modules/driver/cpp/samples/metavision_file_cutter/metavision_file_cutter.cpp @@ -94,7 +94,6 @@ int main(int argc, char *argv[]) { } writer->add_metadata_map_from_camera(camera); - writer->add_metadata("time_shift", std::to_string(start_ts)); std::atomic done(false); if (out_file_ext == ".raw") { @@ -114,6 +113,9 @@ int main(int argc, char *argv[]) { } }); } else { + // Only makes sense when used with post decoder (i.e. not raw) stream as the decoder will apply a time-shift + writer->add_metadata("time_shift", std::to_string(start_ts)); + camera.cd().add_callback([&done, &writer, start_ts, end_ts](const Metavision::EventCD *begin, const Metavision::EventCD *end) { if (done) { diff --git a/sdk/modules/driver/cpp/apps/metavision_file_cutter/test/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_file_cutter/test/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_cutter/test/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_file_cutter/test/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/apps/metavision_file_cutter/test/metavision_file_cutter_pytest.py b/sdk/modules/driver/cpp/samples/metavision_file_cutter/test/metavision_file_cutter_pytest.py similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_cutter/test/metavision_file_cutter_pytest.py rename to sdk/modules/driver/cpp/samples/metavision_file_cutter/test/metavision_file_cutter_pytest.py diff --git a/sdk/modules/driver/cpp/apps/metavision_file_info/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt similarity index 87% rename from sdk/modules/driver/cpp/apps/metavision_file_info/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt index 2fad084b4..38a97cd18 100644 --- a/sdk/modules/driver/cpp/apps/metavision_file_info/CMakeLists.txt +++ b/sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt @@ -16,13 +16,13 @@ install(TARGETS metavision_file_info ) install(FILES metavision_file_info.cpp - DESTINATION share/metavision/sdk/driver/apps/metavision_file_info + DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_info COMPONENT metavision-sdk-driver-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/apps/metavision_file_info + DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_info COMPONENT metavision-sdk-driver-samples ) diff --git a/sdk/modules/driver/cpp/apps/metavision_file_info/CMakeLists.txt.install b/sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt.install similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_info/CMakeLists.txt.install rename to sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt.install diff --git a/sdk/modules/driver/cpp/apps/metavision_file_info/metavision_file_info.cpp b/sdk/modules/driver/cpp/samples/metavision_file_info/metavision_file_info.cpp similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_info/metavision_file_info.cpp rename to sdk/modules/driver/cpp/samples/metavision_file_info/metavision_file_info.cpp diff --git a/sdk/modules/driver/cpp/apps/metavision_file_info/test/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_file_info/test/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_info/test/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_file_info/test/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/apps/metavision_file_info/test/metavision_file_info_pytest.py b/sdk/modules/driver/cpp/samples/metavision_file_info/test/metavision_file_info_pytest.py similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_info/test/metavision_file_info_pytest.py rename to sdk/modules/driver/cpp/samples/metavision_file_info/test/metavision_file_info_pytest.py diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt index 95449ef11..ac6045ff0 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt +++ b/sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt @@ -14,13 +14,13 @@ add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/driver/samples/${sample} + DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} COMPONENT metavision-sdk-driver-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/samples/${sample} + DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} COMPONENT metavision-sdk-driver-samples ) diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_dat/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt similarity index 87% rename from sdk/modules/driver/cpp/apps/metavision_file_to_dat/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt index 3d480204a..dd7596542 100644 --- a/sdk/modules/driver/cpp/apps/metavision_file_to_dat/CMakeLists.txt +++ b/sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt @@ -16,13 +16,13 @@ install(TARGETS metavision_file_to_dat ) install(FILES metavision_file_to_dat.cpp - DESTINATION share/metavision/sdk/driver/apps/metavision_file_to_dat + DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_to_dat COMPONENT metavision-sdk-driver-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/apps/metavision_file_to_dat + DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_to_dat COMPONENT metavision-sdk-driver-samples ) diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_dat/CMakeLists.txt.install b/sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt.install similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_to_dat/CMakeLists.txt.install rename to sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt.install diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_dat/metavision_file_to_dat.cpp b/sdk/modules/driver/cpp/samples/metavision_file_to_dat/metavision_file_to_dat.cpp similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_to_dat/metavision_file_to_dat.cpp rename to sdk/modules/driver/cpp/samples/metavision_file_to_dat/metavision_file_to_dat.cpp diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_dat/test/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_file_to_dat/test/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_to_dat/test/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_file_to_dat/test/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_dat/test/metavision_file_to_dat_pytest.py b/sdk/modules/driver/cpp/samples/metavision_file_to_dat/test/metavision_file_to_dat_pytest.py similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_to_dat/test/metavision_file_to_dat_pytest.py rename to sdk/modules/driver/cpp/samples/metavision_file_to_dat/test/metavision_file_to_dat_pytest.py diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt similarity index 89% rename from sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt index 95da08a74..02559a160 100644 --- a/sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/CMakeLists.txt +++ b/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt @@ -18,13 +18,13 @@ install(TARGETS metavision_file_to_hdf5 ) install(FILES metavision_file_to_hdf5.cpp - DESTINATION share/metavision/sdk/driver/apps/metavision_file_to_hdf5 + DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_to_hdf5 COMPONENT metavision-sdk-driver-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/apps/metavision_file_to_hdf5 + DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_to_hdf5 COMPONENT metavision-sdk-driver-samples ) diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/CMakeLists.txt.install b/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt.install similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/CMakeLists.txt.install rename to sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt.install diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp b/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp similarity index 93% rename from sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp rename to sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp index 7ce7b10f7..b1080e0f2 100644 --- a/sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp +++ b/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp @@ -29,6 +29,7 @@ namespace po = boost::program_options; int main(int argc, char *argv[]) { std::string in_file_path; + std::string out_hdf5_file_path; const std::string program_desc("Application to convert a file to HDF5 file.\n"); @@ -37,6 +38,7 @@ int main(int argc, char *argv[]) { options_desc.add_options() ("help,h", "Produce help message.") ("input-file,i", po::value(&in_file_path)->required(), "Path to input file.") + ("output-file,o", po::value(&out_hdf5_file_path), "Path to output file.") ; // clang-format on @@ -85,9 +87,11 @@ int main(int argc, char *argv[]) { Metavision::Camera &cam = cam_stage.camera(); // Get the output filename and build a HDF5 file writer - std::string out_hdf5_file_path = boost::filesystem::extension(in_file_path) != "" ? - std::regex_replace(in_file_path, std::regex("\\.[^.]*$"), ".hdf5") : - in_file_path + ".hdf5"; + if (out_hdf5_file_path.empty()) { + out_hdf5_file_path = boost::filesystem::extension(in_file_path) != "" ? + std::regex_replace(in_file_path, std::regex("\\.[^.]*$"), ".hdf5") : + in_file_path + ".hdf5"; + } if (in_file_path == out_hdf5_file_path) { MV_LOG_ERROR() << "Error : input file has HDF5 extension. Please, make sure the input file does not have .hdf5 " "extension or rename it."; diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/test/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/test/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/test/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/test/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/test/metavision_file_to_hdf5_pytest.py b/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/test/metavision_file_to_hdf5_pytest.py similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_file_to_hdf5/test/metavision_file_to_hdf5_pytest.py rename to sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/test/metavision_file_to_hdf5_pytest.py diff --git a/sdk/modules/driver/cpp/apps/metavision_viewer/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt similarity index 88% rename from sdk/modules/driver/cpp/apps/metavision_viewer/CMakeLists.txt rename to sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt index 1ef4b9261..32a4ee6b6 100644 --- a/sdk/modules/driver/cpp/apps/metavision_viewer/CMakeLists.txt +++ b/sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt @@ -19,12 +19,12 @@ install(TARGETS ${sample} ) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/driver/apps/${sample} + DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} COMPONENT metavision-sdk-driver-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/apps/${sample} + DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} COMPONENT metavision-sdk-driver-samples ) \ No newline at end of file diff --git a/sdk/modules/driver/cpp/apps/metavision_viewer/CMakeLists.txt.install b/sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt.install similarity index 100% rename from sdk/modules/driver/cpp/apps/metavision_viewer/CMakeLists.txt.install rename to sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt.install diff --git a/sdk/modules/driver/cpp/apps/metavision_viewer/metavision_viewer.cpp b/sdk/modules/driver/cpp/samples/metavision_viewer/metavision_viewer.cpp similarity index 98% rename from sdk/modules/driver/cpp/apps/metavision_viewer/metavision_viewer.cpp rename to sdk/modules/driver/cpp/samples/metavision_viewer/metavision_viewer.cpp index 3f6744bc1..f0b099022 100644 --- a/sdk/modules/driver/cpp/apps/metavision_viewer/metavision_viewer.cpp +++ b/sdk/modules/driver/cpp/samples/metavision_viewer/metavision_viewer.cpp @@ -181,7 +181,7 @@ int main(int argc, char *argv[]) { const std::string &plugin_name = plugin_sw_info->get_plugin_name(); MV_LOG_INFO() << "Plugin used to open the device:" << plugin_name; } - } catch (Metavision::CameraException &e) { + } catch (Metavision::CameraException &) { // we ignore the exception as some devices will not provide this facility (e.g. HDF5 files) } @@ -343,7 +343,7 @@ int main(int argc, char *argv[]) { try { camera.load(in_cam_config_path); MV_LOG_INFO() << "Settings restored from" << in_cam_config_path; - } catch (Metavision::CameraException &e) {} + } catch (Metavision::CameraException &) {} break; } case 's': { @@ -353,7 +353,7 @@ int main(int argc, char *argv[]) { try { camera.save(out_cam_config_path); MV_LOG_INFO() << "Settings saved to" << out_cam_config_path; - } catch (Metavision::CameraException &e) {} + } catch (Metavision::CameraException &) {} break; } case 'r': { @@ -374,21 +374,21 @@ int main(int argc, char *argv[]) { try { camera.erc_module().enable(!camera.erc_module().is_enabled()); MV_LOG_INFO() << "ERC:" << (camera.erc_module().is_enabled() ? "enabled" : "disabled"); - } catch (Metavision::CameraException &e) {} + } catch (Metavision::CameraException &) {} break; } case '+': { try { camera.erc_module().set_cd_event_rate(camera.erc_module().get_cd_event_rate() + 10000000); MV_LOG_INFO() << "ERC:" << (camera.erc_module().get_cd_event_rate() / 1000000) << "Mev/s"; - } catch (Metavision::CameraException &e) {} + } catch (Metavision::CameraException &) {} break; } case '-': { try { camera.erc_module().set_cd_event_rate(camera.erc_module().get_cd_event_rate() - 10000000); MV_LOG_INFO() << "ERC:" << (camera.erc_module().get_cd_event_rate() / 1000000) << "Mev/s"; - } catch (Metavision::CameraException &e) {} + } catch (Metavision::CameraException &) {} break; } case 'h': diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/CMakeLists.txt b/sdk/modules/driver/cpp/samples/metavision_viewer_android/CMakeLists.txt index e48c078b1..205a8bf50 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/CMakeLists.txt +++ b/sdk/modules/driver/cpp/samples/metavision_viewer_android/CMakeLists.txt @@ -7,7 +7,6 @@ # 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. -lfs_download(/datasets/openeb/gen4_evt3_hand.raw) file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/app/assets ) diff --git a/sdk/modules/driver/cpp/src/camera_live.cpp b/sdk/modules/driver/cpp/src/camera_live.cpp index 0c55b2459..36bc71874 100644 --- a/sdk/modules/driver/cpp/src/camera_live.cpp +++ b/sdk/modules/driver/cpp/src/camera_live.cpp @@ -19,6 +19,7 @@ #include "metavision/hal/facilities/i_event_frame_decoder.h" #include "metavision/hal/facilities/i_hw_identification.h" #include "metavision/hal/facilities/i_plugin_software_info.h" +#include "metavision/sdk/base/events/event_pointcloud.h" #include "metavision/sdk/driver/internal/callback_tag_ids.h" #include "metavision/sdk/driver/internal/camera_error_code_internal.h" #include "metavision/sdk/driver/internal/camera_generation_internal.h" @@ -190,9 +191,10 @@ bool LivePrivate::process_impl(TimingProfilerType *profiler) { ev_buffer_end = ev_buffer + n_rawbytes; const bool has_decode_callbacks = index_manager_.counter_map_.tag_count(CallbackTagIds::DECODE_CALLBACK_TAG_ID); - if (has_decode_callbacks) { - i_events_stream_decoder_->decode(ev_buffer, ev_buffer_end); - t.setNumProcessedElements(n_rawbytes / i_events_stream_decoder_->get_raw_event_size_bytes()); + // Pointcloud is not handled by Camera object. Always do decoding for pointclouds. + if (has_decode_callbacks || device_->get_facility>()) { + i_decoder_->decode(ev_buffer, ev_buffer_end); + t.setNumProcessedElements(n_rawbytes / i_decoder_->get_raw_event_size_bytes()); } // ... then we call the raw buffer callback so that a user has access to some info (e.g last @@ -253,6 +255,7 @@ void LivePrivate::init() { } geometry_.reset(new Geometry(i_geometry)); + i_decoder_ = device_->get_facility(); i_events_stream_decoder_ = device_->get_facility(); generation_.reset(CameraGeneration::Private::build(*device_)); @@ -315,7 +318,7 @@ void LivePrivate::init() { }); } - if (!i_events_stream_decoder_ && !i_histogram_decoder && !i_diff_decoder) { + if (!i_decoder_) { throw CameraException(InternalInitializationErrors::IDecoderNotFound); } diff --git a/sdk/modules/driver/cpp/src/camera_offline_raw.cpp b/sdk/modules/driver/cpp/src/camera_offline_raw.cpp index 5709b3669..610bdd694 100644 --- a/sdk/modules/driver/cpp/src/camera_offline_raw.cpp +++ b/sdk/modules/driver/cpp/src/camera_offline_raw.cpp @@ -276,6 +276,14 @@ void OfflineRawPrivate::init() { i_decoder_ = i_diff_decoder; } + I_EventFrameDecoder *i_pointcloud_decoder = device_->get_facility>(); + if (i_pointcloud_decoder) { + file_reader_->add_read_callback([this](const PointCloud &pc) { + // For now PointClouds are not handled by Camera object + }); + i_decoder_ = i_pointcloud_decoder; + } + if (!i_decoder_) { throw CameraException(InternalInitializationErrors::IDecoderNotFound); } diff --git a/sdk/modules/driver/cpp/src/camera_serialization.cpp b/sdk/modules/driver/cpp/src/camera_serialization.cpp index 86f7f18d8..923c04286 100644 --- a/sdk/modules/driver/cpp/src/camera_serialization.cpp +++ b/sdk/modules/driver/cpp/src/camera_serialization.cpp @@ -19,7 +19,7 @@ #include "metavision/hal/facilities/i_digital_crop.h" #include "metavision/hal/facilities/i_digital_event_mask.h" #include "metavision/hal/facilities/i_erc_module.h" -#include "metavision/hal/facilities/i_event_rate_noise_filter_module.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" #include "metavision/hal/facilities/i_event_trail_filter_module.h" #include "metavision/hal/facilities/i_hw_register.h" #include "metavision/hal/facilities/i_ll_biases.h" @@ -56,8 +56,8 @@ struct FacilityTypeList { // This way, it can be documented that registers will not potentially be overwritten by the // deserialization of other facilities using FacilityTypes = FacilityTypeList; + I_ErcModule, I_EventRateActivityFilterModule, I_EventTrailFilterModule, + I_LL_Biases, I_ROI, I_TriggerIn, I_TriggerOut, I_HW_Register>; auto get_serializable_facilities(const Device &device) { return FacilityTypes::get_facilities(device); @@ -145,7 +145,7 @@ class FacilitySerializer { erc_state->set_cd_event_count(module->get_cd_event_count()); } - void operator()(const I_EventRateNoiseFilterModule *module) { + void operator()(const I_EventRateActivityFilterModule *module) { if (!module) { return; } @@ -194,7 +194,23 @@ class FacilitySerializer { } void operator()(const I_ROI *module) { - // TODO : we need appropriate I_ROI HAL API to serialize this facility + if (!module) { + return; + } + + auto roi_state = state_.mutable_roi_state(); + + roi_state->set_enabled(module->is_enabled()); + roi_state->set_mode(module->get_mode() == I_ROI::Mode::ROI ? DeviceSerialization::RegionOfInterestState::ROI : + DeviceSerialization::RegionOfInterestState::RONI); + + for (auto &w : module->get_windows()) { + auto window_state = roi_state->add_window(); + window_state->set_x(w.x); + window_state->set_width(w.width); + window_state->set_y(w.y); + window_state->set_height(w.height); + } } void operator()(const I_TriggerIn *module) { @@ -341,7 +357,7 @@ class FacilityDeserializer { } } - void operator()(I_EventRateNoiseFilterModule *module) { + void operator()(I_EventRateActivityFilterModule *module) { if (!state_.has_event_rate_noise_filter_state()) { return; } @@ -440,9 +456,6 @@ class FacilityDeserializer { } const auto &roi_state = state_.roi_state(); - if (roi_state.optional_enabled_case() == DeviceSerialization::RegionOfInterestState::kEnabled) { - module->enable(roi_state.enabled()); - } if (roi_state.optional_mode_case() == DeviceSerialization::RegionOfInterestState::kMode) { module->set_mode(roi_state.mode() == DeviceSerialization::RegionOfInterestState::ROI ? I_ROI::Mode::ROI : I_ROI::Mode::RONI); @@ -457,28 +470,8 @@ class FacilityDeserializer { module->set_windows(windows); } - if (roi_state.has_lines() && roi_state.window_size() > 0) { - MV_SDK_LOG_WARNING() << "Ignored ROI lines, ROI window is already set"; - } - - if (roi_state.has_lines()) { - const auto &lines = roi_state.lines(); - if (lines.optional_cols_case() == DeviceSerialization::RegionOfInterestState::ROILines::kCols && - lines.optional_rows_case() == DeviceSerialization::RegionOfInterestState::ROILines::kRows) { - const auto &cols_state = lines.cols(); - std::vector cols(cols_state.size()); - for (size_t i = 0; i < cols_state.size(); ++i) { - cols[i] = cols_state[i] == '1'; - } - std::vector rows(lines.rows().size()); - const auto &rows_state = lines.rows(); - for (size_t i = 0; i < rows_state.size(); ++i) { - rows[i] = rows_state[i] == '1'; - } - module->set_lines(cols, rows); - } else { - MV_SDK_LOG_WARNING() << "Ignored ROI lines : missing rows or cols"; - } + if (roi_state.optional_enabled_case() == DeviceSerialization::RegionOfInterestState::kEnabled) { + module->enable(roi_state.enabled()); } } diff --git a/sdk/modules/driver/cpp/src/event_file_reader.cpp b/sdk/modules/driver/cpp/src/event_file_reader.cpp index 74f2a7d91..b5bdee8fb 100644 --- a/sdk/modules/driver/cpp/src/event_file_reader.cpp +++ b/sdk/modules/driver/cpp/src/event_file_reader.cpp @@ -22,6 +22,7 @@ EventFileReader::Private::Private(EventFileReader &reader, const std::string &pa erc_counter_buffer_cb_mgr_(cb_id_mgr_, CallbackTagIds::READ_CALLBACK_TAG_ID), histogram_cb_mgr_(cb_id_mgr_, CallbackTagIds::READ_CALLBACK_TAG_ID), diff_cb_mgr_(cb_id_mgr_, CallbackTagIds::READ_CALLBACK_TAG_ID), + pointcloud_cb_mgr_(cb_id_mgr_, CallbackTagIds::READ_CALLBACK_TAG_ID), seek_cb_mgr_(cb_id_mgr_, CallbackTagIds::SEEK_CALLBACK_TAG_ID), path_(path), min_t_(-1), @@ -52,6 +53,10 @@ size_t EventFileReader::Private::add_read_callback(const EventFrameReadCallback< return diff_cb_mgr_.add_callback(cb); } +size_t EventFileReader::Private::add_read_callback(const EventFrameReadCallback &cb) { + return pointcloud_cb_mgr_.add_callback(cb); +} + bool EventFileReader::Private::has_read_callbacks() const { return cb_id_mgr_.counter_map_.tag_count(CallbackTagIds::READ_CALLBACK_TAG_ID) > 0; } @@ -91,6 +96,13 @@ void EventFileReader::Private::notify_event_frame(const RawEventFrameDiff &d) { } } +void EventFileReader::Private::notify_event_frame(const PointCloud &pc) { + auto cbs = pointcloud_cb_mgr_.get_cbs(); + for (auto &cb : cbs) { + cb(pc); + } +} + size_t EventFileReader::Private::add_seek_callback(const SeekCompletionCallback &cb) { return seek_cb_mgr_.add_callback(cb); } @@ -194,6 +206,10 @@ size_t EventFileReader::add_read_callback(const EventFrameReadCallbackadd_read_callback(cb); } +size_t EventFileReader::add_read_callback(const EventFrameReadCallback &cb) { + return pimpl_->add_read_callback(cb); +} + bool EventFileReader::has_read_callbacks() const { return pimpl_->has_read_callbacks(); } @@ -230,6 +246,10 @@ void EventFileReader::notify_event_frame(const RawEventFrameDiff &d) { return pimpl_->notify_event_frame(d); } +void EventFileReader::notify_event_frame(const PointCloud &p) { + return pimpl_->notify_event_frame(p); +} + void EventFileReader::notify_seek(timestamp t) { return pimpl_->notify_seek(t); } diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_live_internal.h b/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_live_internal.h index 0dfbb7e41..47b319721 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_live_internal.h +++ b/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_live_internal.h @@ -18,6 +18,7 @@ namespace Metavision { class Device; class I_CameraSynchronization; +class I_Decoder; class I_EventsStreamDecoder; class I_EventsStream; @@ -58,6 +59,7 @@ class LivePrivate : public Camera::Private { std::unique_ptr device_ = nullptr; I_EventsStream *i_events_stream_ = nullptr; I_EventsStreamDecoder *i_events_stream_decoder_ = nullptr; + I_Decoder *i_decoder_ = nullptr; I_CameraSynchronization *i_camera_synchronization_ = nullptr; std::unique_ptr roi_; diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_reader_internal.h b/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_reader_internal.h index ee62fefe7..5a64ab590 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_reader_internal.h +++ b/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_reader_internal.h @@ -34,6 +34,7 @@ class EventFileReader::Private { size_t add_read_callback(const EventsBufferReadCallback &cb); size_t add_read_callback(const EventFrameReadCallback &cb); size_t add_read_callback(const EventFrameReadCallback &cb); + size_t add_read_callback(const EventFrameReadCallback &cb); bool has_read_callbacks() const; size_t add_seek_callback(const SeekCompletionCallback &cb); @@ -46,6 +47,7 @@ class EventFileReader::Private { void notify_events_buffer(const EventERCCounter *begin, const EventERCCounter *end); void notify_event_frame(const RawEventFrameHisto &h); void notify_event_frame(const RawEventFrameDiff &d); + void notify_event_frame(const PointCloud &pc); void notify_seek(timestamp t); bool read(); @@ -65,6 +67,7 @@ class EventFileReader::Private { CallbackManager, size_t> erc_counter_buffer_cb_mgr_; CallbackManager, size_t> histogram_cb_mgr_; CallbackManager, size_t> diff_cb_mgr_; + CallbackManager, size_t> pointcloud_cb_mgr_; CallbackManager seek_cb_mgr_; std::string path_; mutable timestamp min_t_, max_t_, duration_; // cached diff --git a/sdk/modules/driver/cpp/src/protobuf/region_of_interest_state.proto b/sdk/modules/driver/cpp/src/protobuf/region_of_interest_state.proto index d1982a008..e28b06431 100644 --- a/sdk/modules/driver/cpp/src/protobuf/region_of_interest_state.proto +++ b/sdk/modules/driver/cpp/src/protobuf/region_of_interest_state.proto @@ -20,10 +20,4 @@ message RegionOfInterestState { } repeated ROIWindow window = 3; - - message ROILines { - oneof optional_cols { string cols = 1; } - oneof optional_rows { string rows = 2; } - } - ROILines lines = 4; } diff --git a/sdk/modules/driver/cpp/src/raw_event_file_reader.cpp b/sdk/modules/driver/cpp/src/raw_event_file_reader.cpp index d6b395270..e3344ebc9 100644 --- a/sdk/modules/driver/cpp/src/raw_event_file_reader.cpp +++ b/sdk/modules/driver/cpp/src/raw_event_file_reader.cpp @@ -26,6 +26,7 @@ class RAWEventFileReader::Private { reader_(reader), raw_data_cb_mgr_(get_parent_pimpl().cb_id_mgr_, 0), device_(device) { i_events_stream_ = device.get_facility(); i_events_stream_decoder_ = device.get_facility(); + i_decoder_ = device.get_facility(); I_EventDecoder *i_cd_events_decoder = device.get_facility>(); if (i_cd_events_decoder) { @@ -51,24 +52,16 @@ class RAWEventFileReader::Private { }); } - if (i_events_stream_decoder_) { - i_decoder_ = i_events_stream_decoder_; - return; - } - auto i_histogram_decoder = device.get_facility>(); if (i_histogram_decoder) { i_histogram_decoder->add_event_frame_callback( [this](const RawEventFrameHisto &h) { reader_.notify_event_frame(h); }); - i_decoder_ = i_histogram_decoder; - return; } auto i_diff_decoder = device.get_facility>(); if (i_diff_decoder) { i_diff_decoder->add_event_frame_callback( [this](const RawEventFrameDiff &d) { reader_.notify_event_frame(d); }); - i_decoder_ = i_diff_decoder; } } diff --git a/sdk/modules/driver/cpp/src/roi.cpp b/sdk/modules/driver/cpp/src/roi.cpp index e10953040..e76063f16 100644 --- a/sdk/modules/driver/cpp/src/roi.cpp +++ b/sdk/modules/driver/cpp/src/roi.cpp @@ -22,6 +22,7 @@ Roi::~Roi() {} void Roi::set(Window roi) { auto roi_to_set = I_ROI::Window(roi.x, roi.y, roi.width, roi.height); pimpl_->set_window(roi_to_set); + pimpl_->enable(true); } void Roi::set(const std::vector &cols, const std::vector &rows) { diff --git a/sdk/modules/driver/cpp/tests/CMakeLists.txt b/sdk/modules/driver/cpp/tests/CMakeLists.txt index 9066bfff0..bea7c07cc 100644 --- a/sdk/modules/driver/cpp/tests/CMakeLists.txt +++ b/sdk/modules/driver/cpp/tests/CMakeLists.txt @@ -60,7 +60,7 @@ add_dependencies(gtest_metavision_sdk_driver hal_dummy_test_plugin) # current binary dir). target_compile_definitions(gtest_metavision_sdk_driver PRIVATE HAL_DUMMY_TEST_PLUGIN="${CMAKE_CURRENT_BINARY_DIR}/../../../../../hal/cpp/test/plugins") -find_package(Protobuf 3.15) +find_package(Protobuf) if (Protobuf_FOUND) target_compile_definitions(gtest_metavision_sdk_driver PRIVATE HAS_PROTOBUF) endif() diff --git a/sdk/modules/driver/cpp/tests/camera_gtest.cpp b/sdk/modules/driver/cpp/tests/camera_gtest.cpp index 74784b821..b92680a78 100644 --- a/sdk/modules/driver/cpp/tests/camera_gtest.cpp +++ b/sdk/modules/driver/cpp/tests/camera_gtest.cpp @@ -24,7 +24,7 @@ #include "metavision/hal/facilities/i_camera_synchronization.h" #include "metavision/hal/facilities/i_digital_crop.h" #include "metavision/hal/facilities/i_digital_event_mask.h" -#include "metavision/hal/facilities/i_event_rate_noise_filter_module.h" +#include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" #include "metavision/hal/facilities/i_events_stream_decoder.h" #include "metavision/hal/facilities/i_hw_register.h" #include "metavision/hal/facilities/i_trigger_in.h" @@ -428,7 +428,7 @@ TEST_F(Camera_Gtest, raw_default_constructor) { Camera camera = Camera::from_file(tmp_file_); const CameraConfiguration &camera_configuration = camera.get_camera_configuration(); ASSERT_NE(camera_configuration.serial_number, ""); - } catch (CameraException &e) { FAIL(); } + } catch (CameraException &) { FAIL(); } try { Camera camera = Camera::from_file("non_existing_file.raw"); @@ -718,7 +718,7 @@ TEST_F(Camera_Gtest, raw_events_callbacks) { Camera camera; try { camera = Camera::from_file(tmp_file_); - } catch (CameraException &e) { FAIL(); } + } catch (CameraException &) { FAIL(); } size_t total_size = 0; CallbackId id = @@ -752,7 +752,7 @@ TEST_F(Camera_Gtest, raw_events_callbacks_decoding_check) { Camera camera; try { camera = Camera::from_file(tmp_file_); - } catch (CameraException &e) { FAIL(); } + } catch (CameraException &) { FAIL(); } camera.raw_data().add_callback([i_events_stream_decoder](const uint8_t *data, size_t size) { auto raw_data_begin = const_cast(data); @@ -1143,7 +1143,7 @@ TEST_F(Camera_Gtest, decode_evt2_data) { Camera camera; try { camera = Camera::from_file(tmp_file_, FileConfigHints().real_time_playback(false)); - } catch (CameraException &e) { FAIL(); } + } catch (CameraException &) { FAIL(); } camera.cd().add_callback( [&](auto ev_begin, auto ev_end) { received_events.insert(received_events.end(), ev_begin, ev_end); }); @@ -1442,6 +1442,8 @@ TEST_F(Camera_Gtest, should_load_serialized_state) { setenv("MV_HAL_PLUGIN_PATH", s.c_str(), 1); #endif + std::vector roi_windows = {{150, 200, 150, 300}, {10, 10, 20, 20}, {1, 2, 3, 4}}; + { Camera camera = Camera::from_serial(Camera_Gtest::dummy_serial_); // AFK @@ -1476,8 +1478,8 @@ TEST_F(Camera_Gtest, should_load_serialized_state) { camera.get_device().get_facility()->set("c", 4); // NFL - camera.get_device().get_facility()->set_event_rate_threshold(14237); - camera.get_device().get_facility()->enable(true); + camera.get_device().get_facility()->set_event_rate_threshold(14237); + camera.get_device().get_facility()->enable(true); // TriggerIn camera.get_device().get_facility()->enable(I_TriggerIn::Channel::Main); @@ -1489,6 +1491,11 @@ TEST_F(Camera_Gtest, should_load_serialized_state) { camera.get_device().get_facility()->set_duty_cycle(0.73); camera.get_device().get_facility()->enable(); + // ROI + camera.get_device().get_facility()->set_mode(I_ROI::Mode::ROI); + camera.get_device().get_facility()->set_windows(roi_windows); + camera.get_device().get_facility()->enable(true); + EXPECT_TRUE(camera.save(tmpdir_handler_->get_full_path("dummy_camera_state.json"))); } { @@ -1546,8 +1553,9 @@ TEST_F(Camera_Gtest, should_load_serialized_state) { EXPECT_EQ(4, camera.get_device().get_facility()->get("c")); // NFL - EXPECT_EQ(14237, camera.get_device().get_facility()->get_event_rate_threshold()); - EXPECT_TRUE(camera.get_device().get_facility()->is_enabled()); + EXPECT_EQ(14237, + camera.get_device().get_facility()->get_event_rate_threshold()); + EXPECT_TRUE(camera.get_device().get_facility()->is_enabled()); // TriggerIn EXPECT_TRUE(camera.get_device().get_facility()->is_enabled(I_TriggerIn::Channel::Main)); @@ -1558,28 +1566,14 @@ TEST_F(Camera_Gtest, should_load_serialized_state) { EXPECT_EQ(2437, camera.get_device().get_facility()->get_period()); EXPECT_DOUBLE_EQ(0.73, camera.get_device().get_facility()->get_duty_cycle()); EXPECT_TRUE(camera.get_device().get_facility()->is_enabled()); + + // ROI + EXPECT_EQ(I_ROI::Mode::ROI, camera.get_device().get_facility()->get_mode()); + EXPECT_TRUE(camera.get_device().get_facility()->is_enabled()); + EXPECT_EQ(roi_windows, camera.get_device().get_facility()->get_windows()); } } -// This facility is declared here so that we can access it directly in the gtest -// because it is exposing fields that should instead be accesible via I_ROI API -// TODO MV-1443 : remove this and override public virtual functions from HAL API, and use -// those functions in the test -namespace Test { -struct DummyROI : public I_ROI { - bool enable(bool state) override; - bool set_mode(const Mode &mode) override; - size_t get_max_supported_windows_count() const override; - bool set_lines(const std::vector &cols, const std::vector &rows) override; - bool set_windows_impl(const std::vector &windows) override; - - bool enabled_{false}; - Mode mode_; - std::vector windows_; - std::vector rows_, cols_; -}; -} // namespace Test - TEST_F(Camera_Gtest, should_load_hand_written_state) { const std::string dummy_plugin_test_path(HAL_DUMMY_TEST_PLUGIN); const char *env = getenv("MV_HAL_PLUGIN_PATH"); @@ -1600,7 +1594,7 @@ TEST_F(Camera_Gtest, should_load_hand_written_state) { ASSERT_TRUE(ofs.is_open()); ofs << R"({ - "hw_register_state": { + "hw_register_state": { "num_access": [ { "address": 12, @@ -1612,7 +1606,7 @@ TEST_F(Camera_Gtest, should_load_hand_written_state) { }, { "address": 3, - "value": 812 + "value": 812 } ], "str_access": [ @@ -1634,7 +1628,7 @@ TEST_F(Camera_Gtest, should_load_hand_written_state) { } ] }, - "ll_biases_state": { + "ll_biases_state": { "bias": [ { "name": "a", @@ -1682,7 +1676,7 @@ TEST_F(Camera_Gtest, should_load_hand_written_state) { ASSERT_TRUE(ofs.is_open()); ofs << R"({ - "roi_state": { + "roi_state": { "enabled": true, "mode": "RONI", "window": [ @@ -1709,54 +1703,10 @@ TEST_F(Camera_Gtest, should_load_hand_written_state) { auto *roi = camera.get_device().get_facility(); EXPECT_TRUE(roi != nullptr); - // TODO MV-1443 : use roi and HAL functions from the API directly - auto *dummy_roi = dynamic_cast<::Test::DummyROI *>(roi); - EXPECT_TRUE(dummy_roi != nullptr); - EXPECT_TRUE(dummy_roi->enabled_); - EXPECT_EQ(I_ROI::Mode::RONI, dummy_roi->mode_); - EXPECT_EQ(I_ROI::Window(12, 19, 213, 334), dummy_roi->windows_[0]); - EXPECT_EQ(I_ROI::Window(4, 32, 13, 384), dummy_roi->windows_[1]); - } - - // ROI : lines - { - Camera camera = Camera::from_serial(Camera_Gtest::dummy_serial_); - std::ofstream ofs(tmpdir_handler_->get_full_path("dummy_camera_state.json")); - ASSERT_TRUE(ofs.is_open()); - - ofs << R"({ - "roi_state": { - "enabled": true, - "mode": "ROI", - "lines": { - "rows": "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010", - "cols": "0110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110110" - } - } -})"; - } - { - Camera camera = Camera::from_serial(Camera_Gtest::dummy_serial_); - EXPECT_TRUE(camera.load(tmpdir_handler_->get_full_path("dummy_camera_state.json"))); - - auto *roi = camera.get_device().get_facility(); - EXPECT_TRUE(roi != nullptr); - - // TODO MV-1443 : use roi and HAL functions from the API directly - auto *dummy_roi = dynamic_cast<::Test::DummyROI *>(roi); - EXPECT_TRUE(dummy_roi != nullptr); - EXPECT_TRUE(dummy_roi->enabled_); - EXPECT_EQ(I_ROI::Mode::ROI, dummy_roi->mode_); - std::vector rows(480); - for (size_t i = 0; i < 480; ++i) { - rows[i] = i % 2 == 0 ? true : false; - } - EXPECT_EQ(rows, dummy_roi->rows_); - std::vector cols(640); - for (size_t i = 0; i < 640; ++i) { - cols[i] = i % 3 == 0 ? false : true; - } - EXPECT_EQ(cols, dummy_roi->cols_); + EXPECT_TRUE(roi->is_enabled()); + EXPECT_EQ(I_ROI::Mode::RONI, roi->get_mode()); + EXPECT_EQ(I_ROI::Window(12, 19, 213, 334), roi->get_windows()[0]); + EXPECT_EQ(I_ROI::Window(4, 32, 13, 384), roi->get_windows()[1]); } } #endif diff --git a/sdk/modules/ui/cpp/samples/metavision_simple_window/CMakeLists.txt b/sdk/modules/ui/cpp/samples/metavision_simple_window/CMakeLists.txt index 30c6034f3..351772c9b 100644 --- a/sdk/modules/ui/cpp/samples/metavision_simple_window/CMakeLists.txt +++ b/sdk/modules/ui/cpp/samples/metavision_simple_window/CMakeLists.txt @@ -25,10 +25,10 @@ target_include_directories(${sample} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(${sample} PRIVATE ${common_libraries} opencv_highgui) install(FILES ${sample}.cpp constants.cpp.in constants.h prophesee_logo.jpg - DESTINATION share/metavision/sdk/ui/samples/${sample} + DESTINATION share/metavision/sdk/ui/cpp_samples/${sample} COMPONENT metavision-sdk-ui-samples) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/ui/samples/${sample} + DESTINATION share/metavision/sdk/ui/cpp_samples/${sample} COMPONENT metavision-sdk-ui-samples) diff --git a/standalone_samples/CMakeLists.txt b/standalone_samples/CMakeLists.txt index 84f3efafc..ef834c052 100644 --- a/standalone_samples/CMakeLists.txt +++ b/standalone_samples/CMakeLists.txt @@ -19,7 +19,7 @@ foreach(sample ${standalone_sample}) # Install sample in package metavision-decoders-samples install(DIRECTORY ${sample} - DESTINATION share/metavision/samples + DESTINATION share/metavision/standalone_samples COMPONENT metavision-decoders-samples ) endforeach(sample) diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index faceaead2..4f0a28aa4 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -8,11 +8,5 @@ # See the License for the specific language governing permissions and limitations under the License. add_subdirectory(cpp) - -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/python/CMakeLists.txt") - add_subdirectory(python) -endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/python/CMakeLists.txt") - -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/windows/CMakeLists.txt") - add_subdirectory(windows) -endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/windows/CMakeLists.txt") \ No newline at end of file +add_subdirectory_if_exists(python) +add_subdirectory_if_exists(windows)