├── .clang-format ├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── event-based_vision_PROPHESEE.png ├── prophesee_event_msgs ├── CHANGELOG.rst ├── CMakeLists.txt ├── msg │ ├── Event.msg │ └── EventArray.msg └── package.xml ├── prophesee_ros_driver ├── CHANGELOG.rst ├── CMakeLists.txt ├── cfg │ ├── gen3_low_sensitive_settings.bias │ ├── gen3_lower_bg_noise.bias │ └── imx636_CD_less_sensitive.bias ├── include │ └── prophesee_ros_driver │ │ ├── cd_frame_generator.h │ │ ├── prophesee_ros_publisher.h │ │ └── prophesee_ros_viewer.h ├── launch │ ├── prophesee_publisher.launch │ └── prophesee_viewer.launch ├── package.xml └── src │ ├── cd_frame_generator.cpp │ ├── prophesee_ros_publisher.cpp │ └── prophesee_ros_viewer.cpp └── prophesee_ros_wrapper ├── CHANGELOG.rst ├── CMakeLists.txt └── package.xml /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: WebKit 4 | AccessModifierOffset: -4 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: true 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlinesLeft: true 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: true 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: Empty 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | # AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: true 21 | BinPackArguments: true 22 | BinPackParameters: true 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: true 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | BeforeCatch: false 33 | BeforeElse: false 34 | IndentBraces: false 35 | BreakBeforeBinaryOperators: None 36 | BreakBeforeBraces: Attach 37 | BreakBeforeInheritanceComma: false 38 | BreakBeforeTernaryOperators: false 39 | BreakConstructorInitializers: AfterColon 40 | # BreakAfterJavaFieldAnnotations: false 41 | BreakStringLiterals: true 42 | ColumnLimit: 120 43 | CommentPragmas: '^ IWYU pragma:' 44 | CompactNamespaces: false 45 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 46 | ConstructorInitializerIndentWidth: 4 47 | ContinuationIndentWidth: 4 48 | Cpp11BracedListStyle: true 49 | DerivePointerAlignment: false 50 | DisableFormat: false 51 | ExperimentalAutoDetectBinPacking: false 52 | FixNamespaceComments: true 53 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 54 | IncludeCategories: 55 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 56 | Priority: 2 57 | - Regex: '^(<|"(gtest|isl|json)/)' 58 | Priority: 3 59 | - Regex: '.*' 60 | Priority: 1 61 | IncludeIsMainRegex: '$' 62 | IndentCaseLabels: false 63 | IndentWidth: 4 64 | IndentWrappedFunctionNames: true 65 | # JavaScriptQuotes: Leave 66 | # JavaScriptWrapImports: true 67 | KeepEmptyLinesAtTheStartOfBlocks: false 68 | MacroBlockBegin: '' 69 | MacroBlockEnd: '' 70 | MaxEmptyLinesToKeep: 1 71 | NamespaceIndentation: None 72 | # ObjCBlockIndentWidth: 4 73 | # ObjCSpaceAfterProperty: true 74 | # ObjCSpaceBeforeProtocolList: true 75 | PenaltyBreakBeforeFirstCallParameter: 19 76 | PenaltyBreakComment: 300 77 | PenaltyBreakFirstLessLess: 120 78 | PenaltyBreakString: 1000 79 | PenaltyExcessCharacter: 1000000 80 | PenaltyReturnTypeOnItsOwnLine: 60 81 | PointerAlignment: Right 82 | ReflowComments: true 83 | SortIncludes: false 84 | SortUsingDeclarations: false 85 | SpaceAfterCStyleCast: false 86 | SpaceAfterTemplateKeyword: false 87 | SpaceBeforeAssignmentOperators: true 88 | SpaceBeforeParens: ControlStatements 89 | SpaceInEmptyParentheses: false 90 | SpacesBeforeTrailingComments: 1 91 | SpacesInAngles: false 92 | SpacesInContainerLiterals: false 93 | SpacesInCStyleCastParentheses: false 94 | SpacesInParentheses: false 95 | SpacesInSquareBrackets: false 96 | Standard: Cpp11 97 | TabWidth: 4 98 | UseTab: Never 99 | ... 100 | 101 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2020 Prophesee 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Prophesee ROS Wrapper 2 | 3 | ![Event-based vision by Prophesee](event-based_vision_PROPHESEE.png) 4 | 5 | The aim of this metapackage is wrapping event-based data from [Prophesee sensors](https://www.prophesee.ai/event-based-sensor-packaged) using [OpenEB](https://github.com/prophesee-ai/openeb) software and publishing the event-based data to ROS. 6 | 7 | This metapackage contains ROS wrapper (prophesee_ros_driver) and messages (prophesee_event_msgs) for Prophesee sensors. 8 | 9 | prophesee_ros_driver is a ROS wrapper including the following nodes: 10 | * prophesee_ros_publisher - publishing data from Prophesee sensor to ROS topics 11 | * prophesee_ros_viewer - listening data from ROS topics and visualizing them on a screen 12 | 13 | prophesee_event_msgs package contains ROS message types for Prophesee event-based data, including: 14 | * Event - an event from a Prophesee camera (uint16 x, uint16 y, ros::Time ts, bool polarity) 15 | * EventArray - a buffer of events (Event[] events) 16 | 17 | Supported [Prophesee Evaluation Kit Cameras](https://docs.prophesee.ai/stable/hw/evk/index.html) : 18 | * EVKV2 - HD 19 | * EVKV3 - VGA/320/HD 20 | * EVKV4 - HD 21 | 22 | ## Requirements 23 | 24 | * Ubuntu 20.04, 22.04 or 24.04 64-bit 25 | * ROS Noetic 26 | * curl (`sudo apt install curl`) 27 | * On Ubuntu 22 and 24, you also need to install libcurl4-openssl-dev by running `sudo apt install libcurl4-openssl-dev` 28 | * [OpenEB](https://github.com/prophesee-ai/openeb) 29 | 30 | ## Installation 31 | 32 | First, retrieve and compile [OpenEB](https://github.com/prophesee-ai/openeb). 33 | 34 | Then, compile the packages: 35 | 36 | * Clone the source code to your catkin workspace ([create a workspace](http://wiki.ros.org/catkin/Tutorials/create_a_workspace), if needed) 37 | 38 | ``` 39 | cd catkin_ws/src 40 | git clone https://github.com/prophesee-ai/prophesee_ros_wrapper.git 41 | cd .. 42 | ``` 43 | 44 | * Compile 45 | 46 | ``` 47 | catkin_make 48 | ``` 49 | 50 | * Source the workspace 51 | 52 | ``` 53 | source ~/catkin_ws/devel/setup.bash 54 | ``` 55 | 56 | 57 | 58 | ## Getting Started 59 | 60 | ### Publishing data from a camera and listening to them 61 | 62 | To publish data from Prophesee camera to ROS topics, run: 63 | 64 | ``` 65 | roslaunch prophesee_ros_driver prophesee_publisher.launch 66 | ``` 67 | 68 | The following topics will be published: 69 | 70 | * /prophesee/camera/cd_events_buffer - buffer of CD (Change Detection) events 71 | * /prophesee/camera/camera_info - information about the camera 72 | 73 | To listen data from ROS topics and visualize them: 74 | 75 | ``` 76 | roslaunch prophesee_ros_driver prophesee_viewer.launch 77 | ``` 78 | 79 | ### Recording data from a live camera to rosbag 80 | 81 | To record data from live camera to rosbag: 82 | * Start the publisher: 83 | 84 | ``` 85 | roslaunch prophesee_ros_driver prophesee_publisher.launch 86 | ``` 87 | 88 | * Start rosbag recording (choose the topics to record or record all available topics): 89 | 90 | ``` 91 | rosbag record -a 92 | ``` 93 | 94 | ### Publishing data from a RAW file 95 | 96 | To publish data from RAW file to ROS topics and view the data: 97 | 98 | * Update the prophesee_publisher.launch file to set the path to your RAW file (in `raw_file_to_read` parameter) 99 | 100 | ``` 101 | rosed prophesee_ros_driver prophesee_publisher.launch 102 | ``` 103 | 104 | * Start the ROS core 105 | 106 | ``` 107 | roscore 108 | ``` 109 | 110 | * Start the viewer, at first to be sure to not miss any data: 111 | 112 | ``` 113 | roslaunch prophesee_ros_driver prophesee_viewer.launch 114 | ``` 115 | 116 | * Start the publisher: 117 | 118 | ``` 119 | roslaunch prophesee_ros_driver prophesee_publisher.launch 120 | ``` 121 | 122 | At the end of the RAW file, the publisher will stop on its own, but the viewer won't stop, so it's up to you to quit the viewer. 123 | 124 | ### Recording data from a RAW file to rosbag 125 | 126 | To record data from RAW file to rosbag: 127 | 128 | * Update the prophesee_publisher.launch file to set the path to your RAW file (in `raw_file_to_read` parameter) 129 | 130 | ``` 131 | rosed prophesee_ros_driver prophesee_publisher.launch 132 | ``` 133 | 134 | * Start the ROS core 135 | 136 | ``` 137 | roscore 138 | ``` 139 | 140 | * Start rosbag recording (choose the topics to record or record all available topics): 141 | 142 | ``` 143 | rosbag record -a 144 | ``` 145 | 146 | * Start the publisher: 147 | 148 | ``` 149 | roslaunch prophesee_ros_driver prophesee_publisher.launch 150 | ``` 151 | 152 | ## Going Further 153 | The ROS wrapper we propose in this repo is a minimal example to get you started. 154 | There are multiple ways to enhance it in terms of features and performance. 155 | The code is open to contributions, thus do not hesitate to [propose pull requests](https://github.com/prophesee-ai/prophesee_ros_wrapper/pulls). 156 | 157 | We also recommend you to check the [metavision_ros_driver repo from berndpfrommer](https://github.com/berndpfrommer/metavision_ros_driver) 158 | that offers a ROS driver for event-based cameras with some speed and features enhancements. 159 | 160 | ## Contact 161 | In case of any issue, please [raise an issue here on GitHub](https://github.com/prophesee-ai/prophesee_ros_wrapper/issues). 162 | For any other information [contact us](https://www.prophesee.ai/contact-us/). 163 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /event-based_vision_PROPHESEE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prophesee-ai/prophesee_ros_wrapper/a8528e8cb2fefe5b7161e8abda994d06d4aee5df/event-based_vision_PROPHESEE.png -------------------------------------------------------------------------------- /prophesee_event_msgs/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package prophesee_event_msgs 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 0.0.2 (2019-10-09) 6 | ------------------ 7 | 8 | 0.0.1 (2019-10-09) 9 | ------------------ 10 | * Merge pull request #4 from uzh-rpg/master 11 | Event messages harmonization with existing event-based sensors within the ROS ecosystem 12 | * prophesee_event_msgs: correct comment in Event ros message. 13 | * Merge branch 'master' of github.com:uzh-rpg/prophesee_ros_wrapper 14 | * prophesee_event_msgs: event buffer with header. events with ros::Time as timestamp 15 | prophesee_ros_driver: adapt driver and visualizer to the new event messages. 16 | * Initial version 17 | * Contributors: Javier Hidalgo-Carrió, Natalia Lyubova, meliortony 18 | -------------------------------------------------------------------------------- /prophesee_event_msgs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(prophesee_event_msgs) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | message_generation 6 | std_msgs 7 | ) 8 | 9 | ## Generate messages in the 'msg' folder 10 | add_message_files( 11 | FILES 12 | Event.msg 13 | EventArray.msg 14 | ) 15 | 16 | ## Generate added messages with dependencies listed here 17 | generate_messages( 18 | DEPENDENCIES 19 | std_msgs 20 | ) 21 | 22 | catkin_package( 23 | CATKIN_DEPENDS message_runtime std_msgs 24 | ) 25 | -------------------------------------------------------------------------------- /prophesee_event_msgs/msg/Event.msg: -------------------------------------------------------------------------------- 1 | # A single event message 2 | uint16 x 3 | uint16 y 4 | time ts 5 | bool polarity 6 | -------------------------------------------------------------------------------- /prophesee_event_msgs/msg/EventArray.msg: -------------------------------------------------------------------------------- 1 | # This message contains an array of events 2 | # (0, 0) is at top-left corner of image 3 | # 4 | 5 | Header header 6 | 7 | uint32 height # image height, that is, number of rows 8 | uint32 width # image width, that is, number of columns 9 | 10 | # an array of events 11 | Event[] events 12 | -------------------------------------------------------------------------------- /prophesee_event_msgs/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | prophesee_event_msgs 4 | 0.0.2 5 | Prophesee event-based camera message package 6 | 7 | Natalia Lyubova 8 | Natalia Lyubova 9 | Egor Makhov 10 | 11 | Apache 2.0 12 | 13 | catkin 14 | 15 | std_msgs 16 | message_generation 17 | 18 | std_msgs 19 | 20 | std_msgs 21 | message_runtime 22 | 23 | 24 | -------------------------------------------------------------------------------- /prophesee_ros_driver/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package prophesee_ros_driver 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 0.0.2 (2019-10-09) 6 | ------------------ 7 | 8 | 0.0.1 (2019-10-09) 9 | ------------------ 10 | * Merge pull request #5 from a-tonda/hotfix/ubuntu_versions_compatibility 11 | [FIX] test ubuntu version to set OpenCV path accordingly 12 | * Merge pull request #4 from uzh-rpg/master 13 | Event messages harmonization with existing event-based sensors within the ROS ecosystem 14 | * Merge branch 'master' of github.com:uzh-rpg/prophesee_ros_wrapper 15 | * [COMPILE] adapt for prophesee release 1.3.0 16 | * prophesee_event_msgs: event buffer with header. events with ros::Time as timestamp 17 | prophesee_ros_driver: adapt driver and visualizer to the new event messages. 18 | * Merge pull request #3 from uzh-rpg/master 19 | Include IMU readings 20 | * prophesee_ros_driver: publish IMU events measurements in IMU frame. 21 | prophesee_ros_driver: publish IMU data by default in launch file 22 | * Initial version 23 | * Contributors: Arnaud Tonda, Javier Hidalgo-Carrió, Natalia Lyubova, meliortony 24 | -------------------------------------------------------------------------------- /prophesee_ros_driver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(prophesee_ros_driver) 3 | 4 | ## Compile as C++11, supported in ROS Kinetic and newer 5 | add_compile_options(-std=c++17 -O3) 6 | 7 | 8 | execute_process(COMMAND lsb_release -cs OUTPUT_VARIABLE RELEASE_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE) 9 | 10 | find_package(OpenCV COMPONENTS highgui REQUIRED) 11 | 12 | find_package(catkin REQUIRED COMPONENTS 13 | OpenCV 14 | roscpp 15 | sensor_msgs 16 | cv_bridge 17 | image_transport 18 | prophesee_event_msgs 19 | genmsg 20 | message_generation 21 | ) 22 | 23 | find_package(MetavisionSDK COMPONENTS stream REQUIRED) 24 | 25 | if (CATKIN_ENABLE_TESTING) 26 | find_package(roslaunch REQUIRED) 27 | roslaunch_add_file_check(launch) 28 | endif() 29 | 30 | catkin_package( 31 | INCLUDE_DIRS include/${PROJECT_NAME}/ 32 | LIBRARIES ${PROJECT_NAME} 33 | CATKIN_DEPENDS roscpp sensor_msgs cv_bridge image_transport prophesee_event_msgs 34 | ) 35 | 36 | ########### 37 | ## Build ## 38 | ########### 39 | 40 | include_directories( 41 | include/${PROJECT_NAME} 42 | ${catkin_INCLUDE_DIRS} 43 | ${OPENCV_INCLUDE_DIRS} 44 | ) 45 | 46 | # Prophesee Publisher 47 | add_executable(prophesee_ros_publisher 48 | src/prophesee_ros_publisher.cpp 49 | ) 50 | 51 | target_link_libraries( 52 | prophesee_ros_publisher 53 | MetavisionSDK::stream 54 | ${catkin_LIBRARIES} 55 | curl 56 | ) 57 | 58 | add_dependencies( 59 | prophesee_ros_publisher 60 | prophesee_event_msgs_generate_messages_cpp 61 | ${catkin_EXPORTED_TARGETS} 62 | ) 63 | 64 | # Prophesee Viewer 65 | add_executable(prophesee_ros_viewer 66 | src/prophesee_ros_viewer.cpp 67 | src/cd_frame_generator.cpp 68 | ) 69 | 70 | target_link_libraries( 71 | prophesee_ros_viewer 72 | MetavisionSDK::stream 73 | ${catkin_LIBRARIES} 74 | curl 75 | ) 76 | 77 | add_dependencies( 78 | prophesee_ros_viewer 79 | prophesee_event_msgs_generate_messages_cpp 80 | ${catkin_EXPORTED_TARGETS} 81 | curl 82 | ) 83 | -------------------------------------------------------------------------------- /prophesee_ros_driver/cfg/gen3_low_sensitive_settings.bias: -------------------------------------------------------------------------------- 1 | % subsystem_ID 2415920387 2 | % system_ID 21 3 | 300 % bias_latchout_or_pu % v 4 | 100 % bias_reqx_or_pu % v 5 | 1200 % bias_req_pux % v 6 | 1300 % bias_req_puy % v 7 | 500 % bias_del_reqx_or % v 8 | 800 % bias_sendreq_pdx % v 9 | 500 % bias_sendreq_pdy % v 10 | 400 % bias_del_ack_array % v 11 | 200 % bias_del_timeout % v 12 | 400 % bias_inv % v 13 | 1500 % bias_refr % v 14 | 500 % bias_clk % v 15 | 1800 % bias_hpf % v 16 | 430 % bias_tail % i 17 | 230 % bias_out % i 18 | 370 % bias_hyst % i 19 | 1397 % bias_vrefl % v 20 | 1700 % bias_vrefh % v 21 | 1000 % bias_cas % v 22 | 191 % bias_diff_off % v 23 | 439 % bias_diff_on % v 24 | 300 % bias_diff % v 25 | 1720 % bias_fo % v 26 | 1500 % bias_pr % v 27 | 1500 % bias_bulk % v 28 | 1600 % bias_overflow % v 29 | 200 % bias_buf % v 30 | -------------------------------------------------------------------------------- /prophesee_ros_driver/cfg/gen3_lower_bg_noise.bias: -------------------------------------------------------------------------------- 1 | % subsystem_ID 2415920387 2 | % system_ID 21 3 | 300 % bias_latchout_or_pu % v 4 | 100 % bias_reqx_or_pu % v 5 | 1200 % bias_req_pux % v 6 | 1300 % bias_req_puy % v 7 | 500 % bias_del_reqx_or % v 8 | 800 % bias_sendreq_pdx % v 9 | 500 % bias_sendreq_pdy % v 10 | 400 % bias_del_ack_array % v 11 | 200 % bias_del_timeout % v 12 | 400 % bias_inv % v 13 | 1500 % bias_refr % v 14 | 500 % bias_clk % v 15 | 1800 % bias_hpf % v 16 | 430 % bias_tail % i 17 | 230 % bias_out % i 18 | 370 % bias_hyst % i 19 | 1397 % bias_vrefl % v 20 | 1700 % bias_vrefh % v 21 | 1000 % bias_cas % v 22 | 213 % bias_diff_off % v 23 | 411 % bias_diff_on % v 24 | 300 % bias_diff % v 25 | 1720 % bias_fo % v 26 | 1500 % bias_pr % v 27 | 1500 % bias_bulk % v 28 | 1600 % bias_overflow % v 29 | 200 % bias_buf % v 30 | -------------------------------------------------------------------------------- /prophesee_ros_driver/cfg/imx636_CD_less_sensitive.bias: -------------------------------------------------------------------------------- 1 | 0 % bias_diff 2 | 20 % bias_diff_off 3 | 24 % bias_diff_on 4 | -10 % bias_fo 5 | 12 % bias_hpf 6 | 0 % bias_refr 7 | -------------------------------------------------------------------------------- /prophesee_ros_driver/include/prophesee_ros_driver/cd_frame_generator.h: -------------------------------------------------------------------------------- 1 | /******************************************************************* 2 | * File : cd_frame_generator.h * 3 | * * 4 | * Copyright: (c) 2015-2019 Prophesee * 5 | *******************************************************************/ 6 | 7 | #ifndef CD_FRAME_GENERATOR_H_ 8 | #define CD_FRAME_GENERATOR_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | /// \brief Utility class to display CD events 22 | class CDFrameGenerator { 23 | public: 24 | /// \brief Default constructor 25 | CDFrameGenerator(); 26 | 27 | /// \brief Destructor 28 | ~CDFrameGenerator(); 29 | 30 | /// \brief Initializes the frame generator 31 | /// 32 | /// @param width, height : size of the image 33 | void init(long width, long height); 34 | 35 | /// \brief Adds the buffer of events to be displayed 36 | /// 37 | /// @param msg : event buffer message 38 | void add_events(const prophesee_event_msgs::EventArray::ConstPtr &msg); 39 | 40 | /// \brief Sets the time interval to display events 41 | /// 42 | /// The events shown at each refresh are such that their timestamps are in the last 'display_accumulation_time_us' 43 | /// microseconds from the last received event timestamp. 44 | /// \param display_accumulation_time_us the time interval to display events from up to now, in us. 45 | void set_display_accumulation_time_us(long long display_accumulation_time_us); 46 | 47 | /// \brief Starts the generator thread 48 | /// 49 | /// After this, you can call get_current_frame() whenever you want to have the 50 | /// most up to date CD frame to display 51 | /// \return True if the thread started successfully, false otherwise. 52 | /// Also returns false, if the thread is already started. 53 | bool start(); 54 | 55 | /// \brief Stops the generator thread 56 | /// 57 | /// \return True if the thread has been stopped successfully, false otherwise. 58 | // If the thread is not started, this function returns false. 59 | bool stop(); 60 | 61 | /// \brief Resets the frame, the queue of events, and the last processed timestamp 62 | void reset(); 63 | 64 | /// \brief Gets the current most up to date CD frame 65 | /// 66 | /// \return the current frame 67 | const cv::Mat &get_current_frame(); 68 | 69 | /// \brief Gets the last event timestamp in us 70 | /// 71 | /// \return the last event timestamp 72 | const Metavision::timestamp &get_last_event_timestamp() const; 73 | 74 | /// \brief Gets ROS time of the last received event buffer 75 | /// 76 | /// \return ROS time of the last received event buffer 77 | const ros::Time &get_last_ros_timestamp() const; 78 | 79 | /// \brief Converts ROS time into Metavision timestamp 80 | /// 81 | /// \return Timestamp in microseconds 82 | inline Metavision::timestamp ros_timestamp_in_us(const ros::Time &ts) const { 83 | return static_cast(ts.toNSec() / 1000.00); 84 | }; 85 | 86 | private: 87 | // Generate a frame 88 | void generate(); 89 | 90 | // Number of pixels in an image 91 | size_t pix_count_ = 0; 92 | 93 | // Vector of timestamps in us 94 | std::vector ts_history_; 95 | 96 | // Generated image 97 | cv::Mat frame_; 98 | 99 | // Image to display 100 | cv::Mat frame_to_show_; 101 | 102 | // Time interval to display events 103 | uint32_t display_accumulation_time_us_ = 5000; 104 | 105 | // Last event timestamp in us 106 | Metavision::timestamp last_ts_ = 0, last_process_ts_ = 0; 107 | 108 | size_t min_events_to_process_ = 10000; 109 | Metavision::timestamp max_delay_before_processing_ = 5000; 110 | 111 | // Received events 112 | std::vector events_queue_front_; 113 | 114 | // Events to display 115 | std::vector events_queue_back_; 116 | 117 | std::mutex frame_show_mutex_; 118 | std::mutex processing_mutex_; 119 | std::atomic thread_should_process_; 120 | 121 | // The worker thread 122 | std::thread thread_; 123 | std::mutex thread_cond_mutex_; 124 | std::condition_variable thread_cond_; 125 | std::atomic thread_should_stop_; 126 | 127 | // Image width 128 | int width_ = 0; 129 | 130 | // Image height 131 | int height_ = 0; 132 | 133 | /// \brief State of the frame generator: initialized or not 134 | bool initialized_ = false; 135 | 136 | // ROS time of the last received event buffer 137 | ros::Time last_ros_ts_; 138 | }; 139 | 140 | #endif /* CD_FRAME_GENERATOR_H_ */ 141 | -------------------------------------------------------------------------------- /prophesee_ros_driver/include/prophesee_ros_driver/prophesee_ros_publisher.h: -------------------------------------------------------------------------------- 1 | /******************************************************************* 2 | * File : prophesee_ros_publisher.h * 3 | * * 4 | * Copyright: (c) 2015-2019 Prophesee * 5 | *******************************************************************/ 6 | 7 | #ifndef PROPHESEE_ROS_PUBLISHER_H_ 8 | #define PROPHESEE_ROS_PUBLISHER_H_ 9 | 10 | #include 11 | 12 | #include 13 | 14 | /// \brief Main class for ROS publisher 15 | /// 16 | /// Publishes data from Prophesee sensor to ROS topics 17 | class PropheseeWrapperPublisher { 18 | public: 19 | /// \brief Constructor 20 | PropheseeWrapperPublisher(); 21 | 22 | /// \brief Destructor 23 | ~PropheseeWrapperPublisher(); 24 | 25 | /// \brief Starts the camera and starts publishing data 26 | void startPublishing(); 27 | 28 | private: 29 | /// \brief Opens the camera 30 | bool openCamera(); 31 | 32 | /// \brief Publishes CD events 33 | void publishCDEvents(); 34 | 35 | /// \brief Node handler - the access point to communication with ROS 36 | ros::NodeHandle nh_; 37 | 38 | /// \brief Publisher for camera info 39 | ros::Publisher pub_info_; 40 | 41 | /// \brief Publisher for CD events 42 | ros::Publisher pub_cd_events_; 43 | 44 | /// \brief Instance of Camera class 45 | /// 46 | /// Used to access data from a camera 47 | Metavision::Camera camera_; 48 | 49 | /// \brief Instance of Events Array 50 | /// 51 | /// Accumulated Array of events 52 | std::vector event_buffer_; 53 | 54 | /// \brief Message for publishing the camera info 55 | sensor_msgs::CameraInfo cam_info_msg_; 56 | 57 | /// \brief Path to the file with the camera settings (biases) 58 | std::string biases_file_; 59 | 60 | /// \brief Raw file to read instead of live camera 61 | std::string raw_file_to_read_; 62 | 63 | /// \brief Camera name in string format 64 | std::string camera_name_; 65 | 66 | /// \brief Wall timestamps 67 | ros::Time start_timestamp_, last_timestamp_; 68 | 69 | /// \brief If showing CD events 70 | bool publish_cd_; 71 | 72 | /// \brief Activity Filter Temporal depth (configuration) 73 | /// Desirable Temporal depth in micro seconds 74 | int activity_filter_temporal_depth_; 75 | 76 | /// \brief delta_time for packages cd_events 77 | /// Time step for packaging events in an array 78 | ros::Duration event_delta_t_; 79 | 80 | /// \brief Event buffer timestamps 81 | ros::Time event_buffer_start_time_, event_buffer_current_time_; 82 | 83 | /// \brief Mean gravity value at Earth surface [m/s^2] 84 | static constexpr double GRAVITY = 9.81; 85 | 86 | /// \brief delta time of cd events fixed by the driver 87 | /// The delta time is set to a fixed number of 64 microseconds (1e-06) 88 | static constexpr double EVENT_DEFAULT_DELTA_T = 6.4e-05; 89 | }; 90 | 91 | #endif /* PROPHESEE_ROS_PUBLISHER_H_ */ 92 | -------------------------------------------------------------------------------- /prophesee_ros_driver/include/prophesee_ros_driver/prophesee_ros_viewer.h: -------------------------------------------------------------------------------- 1 | /******************************************************************* 2 | * File : prophesee_ros_viewer.h * 3 | * * 4 | * Copyright: (c) 2015-2019 Prophesee * 5 | *******************************************************************/ 6 | 7 | #ifndef PROPHESEE_ROS_VIEWER_H_ 8 | #define PROPHESEE_ROS_VIEWER_H_ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include "cd_frame_generator.h" 22 | 23 | /// \brief Main class ROS listener and viewer 24 | /// 25 | /// Listens ROS topics publishing data from Prophesee cameras and visualizes them on a screen 26 | class PropheseeWrapperViewer { 27 | public: 28 | /// \brief Constructor 29 | PropheseeWrapperViewer(); 30 | 31 | /// \brief Destructor 32 | ~PropheseeWrapperViewer(); 33 | 34 | /// \brief Shows currently available CD data 35 | void showData(); 36 | 37 | /// \brief Checks if the frame generator class is initialized or not 38 | /// 39 | /// @return true if initialized and false otherwise 40 | bool isInitialized(); 41 | 42 | private: 43 | /// \brief Callback triggered when data are received from the camera info topic 44 | /// 45 | /// It gets width and height of the sensor and calls init() function 46 | /// 47 | /// @param msg : ROS message with the camera info 48 | void cameraInfoCallback(const sensor_msgs::CameraInfo::ConstPtr &msg); 49 | 50 | /// \brief Initializes the frame generators and the displayers 51 | /// 52 | /// @param sensor_width : Width of the sensor 53 | /// @param sensor_height : Height of the sensor 54 | /// 55 | /// It initializes CD frame generator with the sensor's width and height. 56 | /// It also creates the displayers. 57 | bool init(const unsigned int &sensor_width, const unsigned int &sensor_height); 58 | 59 | /// \brief Creates a displayer 60 | /// 61 | /// @param window_name The name of the displayer window 62 | /// @param sensor_width : Width of the window 63 | /// @param sensor_height : Height of the window 64 | /// @param shift_x : Position (x shift) of the window 65 | /// @param shift_y : Position (y shift) of the window 66 | void create_window(const std::string &window_name, const unsigned int &sensor_width, 67 | const unsigned int &sensor_height, const int &shift_x = 0, const int &shift_y = 0); 68 | 69 | /// \brief Node handler - the access point to communication with ROS 70 | ros::NodeHandle nh_; 71 | 72 | /// \brief Subscriber to the camera info topic 73 | ros::Subscriber sub_cam_info_; 74 | 75 | /// \brief Subscriber for CD events topic 76 | ros::Subscriber sub_cd_events_; 77 | 78 | /// \brief Instance of CDFrameGenerator class that generates a frame from CD events 79 | CDFrameGenerator cd_frame_generator_; 80 | 81 | /// \brief Window name for visualizing CD events 82 | std::string cd_window_name_; 83 | 84 | /// \brief Display accumulation time 85 | 86 | /// The time interval to display events up to the current time, in us 87 | int display_acc_time_; 88 | 89 | /// \brief If the frame generators are initialized with teh sensor width and height 90 | bool initialized_; 91 | 92 | /// \brief If visualizing CD events 93 | bool show_cd_ = true; 94 | 95 | }; 96 | 97 | #endif /* PROPHESEE_ROS_VIEWER_H_ */ 98 | -------------------------------------------------------------------------------- /prophesee_ros_driver/launch/prophesee_publisher.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /prophesee_ros_driver/launch/prophesee_viewer.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /prophesee_ros_driver/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | prophesee_ros_driver 4 | 0.0.2 5 | Publisher and Viewer for Prophesee Event-Based Sensors 6 | 7 | Natalia Lyubova 8 | Natalia Lyubova 9 | Egor Makhov 10 | 11 | Apache 2.0 12 | 13 | catkin 14 | 15 | prophesee_event_msgs 16 | 17 | roscpp 18 | roslaunch 19 | sensor_msgs 20 | cv_bridge 21 | image_transport 22 | 23 | roscpp 24 | sensor_msgs 25 | 26 | roscpp 27 | sensor_msgs 28 | cv_bridge 29 | image_transport 30 | 31 | 32 | -------------------------------------------------------------------------------- /prophesee_ros_driver/src/cd_frame_generator.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************* 2 | * File : cd_frame_generator.cpp * 3 | * * 4 | * Copyright: (c) 2015-2019 Prophesee * 5 | *******************************************************************/ 6 | 7 | #include "cd_frame_generator.h" 8 | 9 | CDFrameGenerator::CDFrameGenerator() {} 10 | 11 | CDFrameGenerator::~CDFrameGenerator() { 12 | stop(); 13 | } 14 | 15 | void CDFrameGenerator::init(long width, long height) { 16 | width_ = width; 17 | height_ = height; 18 | pix_count_ = height_ * width_; 19 | ts_history_.resize(pix_count_); 20 | 21 | frame_ = cv::Mat(height_, width_, CV_8UC1, cv::Scalar(128)); 22 | frame_to_show_ = cv::Mat(height_, width_, CV_8UC1, cv::Scalar(128)); 23 | 24 | initialized_ = true; 25 | } 26 | 27 | void CDFrameGenerator::add_events(const prophesee_event_msgs::EventArray::ConstPtr &msgs) { 28 | bool should_process = false; 29 | { 30 | std::lock_guard lock(processing_mutex_); 31 | if (std::begin(msgs->events) < std::end(msgs->events)) { 32 | events_queue_front_.insert(events_queue_front_.end(), std::begin(msgs->events), std::end(msgs->events)); 33 | last_ts_ = ros_timestamp_in_us((std::end(msgs->events) - 1)->ts); 34 | } 35 | if (events_queue_front_.size() >= min_events_to_process_ || 36 | last_ts_ >= last_process_ts_ + max_delay_before_processing_) { 37 | should_process = true; 38 | } 39 | } 40 | 41 | if (should_process) { 42 | { thread_should_process_ = true; } 43 | thread_cond_.notify_one(); 44 | } 45 | 46 | last_ros_ts_ = ros::Time::now(); 47 | } 48 | 49 | void CDFrameGenerator::reset() { 50 | if (!initialized_) 51 | return; 52 | 53 | { 54 | std::unique_lock lock_process(processing_mutex_); 55 | thread_should_process_ = false; 56 | last_ts_ = 0; 57 | last_process_ts_ = 0; 58 | 59 | // Clean the queues with events 60 | events_queue_front_.clear(); 61 | events_queue_back_.clear(); 62 | } 63 | 64 | { 65 | // Clean the frame 66 | std::unique_lock lock_show(frame_show_mutex_); 67 | frame_.setTo(cv::Scalar(128)); 68 | frame_to_show_.setTo(cv::Scalar(128)); 69 | 70 | // Clean the pixels timstamps history 71 | ts_history_.assign(ts_history_.size(), 0); 72 | } 73 | 74 | initialized_ = false; 75 | } 76 | 77 | void CDFrameGenerator::generate() { 78 | if (!initialized_) 79 | return; 80 | 81 | while (true) { 82 | { 83 | std::unique_lock lock(thread_cond_mutex_); 84 | thread_cond_.wait(lock, [this] { return thread_should_process_ || thread_should_stop_; }); 85 | } 86 | 87 | if (thread_should_stop_) 88 | break; 89 | 90 | Metavision::timestamp threshold_to_display; 91 | { 92 | std::unique_lock lock(processing_mutex_); 93 | std::swap(events_queue_front_, events_queue_back_); 94 | if (!events_queue_back_.empty()) 95 | last_process_ts_ = ros_timestamp_in_us(events_queue_back_.back().ts); 96 | threshold_to_display = last_ts_ - display_accumulation_time_us_; 97 | } 98 | 99 | if (events_queue_back_.empty()) 100 | continue; 101 | 102 | std::unique_lock lock(frame_show_mutex_); 103 | for (auto it = events_queue_back_.rbegin(), it_end = events_queue_back_.rend(); 104 | it != it_end && ros_timestamp_in_us(it->ts) >= threshold_to_display; ++it) { 105 | Metavision::timestamp &p_ts = ts_history_[it->y * width_ + it->x]; 106 | if (p_ts < ros_timestamp_in_us(it->ts)) { 107 | p_ts = ros_timestamp_in_us(it->ts); 108 | frame_.at(it->y, it->x) = it->polarity ? 255 : 0; 109 | } 110 | } 111 | 112 | auto ts_history_it = ts_history_.begin(); 113 | auto datas = frame_.data; 114 | for (size_t i = 0; i < pix_count_; ++i, ++ts_history_it, ++datas) { 115 | if (*ts_history_it < threshold_to_display) { 116 | *datas = 128; 117 | } 118 | } 119 | 120 | events_queue_back_.clear(); 121 | thread_should_process_ = false; 122 | } 123 | } 124 | 125 | void CDFrameGenerator::set_display_accumulation_time_us(Metavision::timestamp display_accumulation_time_us) { 126 | std::lock_guard lock(processing_mutex_); 127 | display_accumulation_time_us_ = display_accumulation_time_us; 128 | } 129 | 130 | const cv::Mat &CDFrameGenerator::get_current_frame() { 131 | std::unique_lock lock(frame_show_mutex_); 132 | std::swap(frame_to_show_, frame_); 133 | return frame_to_show_; 134 | } 135 | 136 | const Metavision::timestamp &CDFrameGenerator::get_last_event_timestamp() const { 137 | return last_ts_; 138 | } 139 | 140 | const ros::Time &CDFrameGenerator::get_last_ros_timestamp() const { 141 | return last_ros_ts_; 142 | } 143 | 144 | bool CDFrameGenerator::start() { 145 | if (!initialized_) 146 | return false; 147 | 148 | if (thread_.joinable()) { // Already started 149 | return false; 150 | } 151 | 152 | std::unique_lock lock(thread_cond_mutex_); 153 | thread_should_process_ = false; 154 | thread_should_stop_ = false; 155 | thread_ = std::thread([this] { generate(); }); 156 | 157 | return true; 158 | } 159 | 160 | bool CDFrameGenerator::stop() { 161 | if (!thread_.joinable()) { 162 | return false; 163 | } 164 | 165 | { thread_should_stop_ = true; } 166 | 167 | thread_cond_.notify_one(); 168 | thread_.join(); 169 | return true; 170 | } 171 | -------------------------------------------------------------------------------- /prophesee_ros_driver/src/prophesee_ros_publisher.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************* 2 | * File : prophesee_ros_publisher.cpp * 3 | * * 4 | * Copyright: (c) 2015-2019 Prophesee * 5 | *******************************************************************/ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "prophesee_ros_publisher.h" 20 | 21 | #include 22 | 23 | PropheseeWrapperPublisher::PropheseeWrapperPublisher() : 24 | nh_("~"), 25 | biases_file_(""), 26 | raw_file_to_read_("") { 27 | camera_name_ = "PropheseeCamera_optical_frame"; 28 | 29 | // Load Parameters 30 | nh_.getParam("camera_name", camera_name_); 31 | nh_.getParam("publish_cd", publish_cd_); 32 | nh_.getParam("bias_file", biases_file_); 33 | nh_.getParam("raw_file_to_read", raw_file_to_read_); 34 | event_delta_t_ = ros::Duration(nh_.param("event_delta_t", 100.0e-6)); 35 | 36 | const std::string topic_cam_info = "/prophesee/" + camera_name_ + "/camera_info"; 37 | const std::string topic_cd_event_buffer = "/prophesee/" + camera_name_ + "/cd_events_buffer"; 38 | 39 | pub_info_ = nh_.advertise(topic_cam_info, 1); 40 | 41 | if (publish_cd_) 42 | pub_cd_events_ = nh_.advertise(topic_cd_event_buffer, 500); 43 | 44 | while (!openCamera()) { 45 | std::this_thread::sleep_for(std::chrono::seconds(1)); 46 | ROS_INFO("Trying to open camera..."); 47 | } 48 | 49 | // Add camera runtime error callback 50 | camera_.add_runtime_error_callback([](const Metavision::CameraException &e) { ROS_WARN("%s", e.what()); }); 51 | 52 | // Get the sensor config 53 | Metavision::CameraConfiguration config = camera_.get_camera_configuration(); 54 | auto &geometry = camera_.geometry(); 55 | ROS_INFO("[CONF] Width:%i, Height:%i", geometry.get_width(), geometry.get_height()); 56 | ROS_INFO("[CONF] Serial number: %s", config.serial_number.c_str()); 57 | 58 | // Publish camera info message 59 | cam_info_msg_.width = geometry.get_width(); 60 | cam_info_msg_.height = geometry.get_height(); 61 | cam_info_msg_.header.frame_id = "PropheseeCamera_optical_frame"; 62 | } 63 | 64 | PropheseeWrapperPublisher::~PropheseeWrapperPublisher() { 65 | camera_.stop(); 66 | 67 | nh_.shutdown(); 68 | } 69 | 70 | bool PropheseeWrapperPublisher::openCamera() { 71 | bool camera_is_opened = false; 72 | 73 | // Initialize the camera instance 74 | try { 75 | if (raw_file_to_read_.empty()) { 76 | camera_ = Metavision::Camera::from_first_available(); 77 | 78 | if (!biases_file_.empty()) { 79 | ROS_INFO("[CONF] Loading bias file: %s", biases_file_.c_str()); 80 | camera_.get_facility().load_from_file(biases_file_); 81 | } 82 | } else { 83 | camera_ = Metavision::Camera::from_file(raw_file_to_read_); 84 | ROS_INFO("[CONF] Reading from raw file: %s", raw_file_to_read_.c_str()); 85 | } 86 | 87 | camera_is_opened = true; 88 | } catch (Metavision::CameraException &e) { ROS_WARN("%s", e.what()); } 89 | return camera_is_opened; 90 | } 91 | 92 | void PropheseeWrapperPublisher::startPublishing() { 93 | camera_.start(); 94 | start_timestamp_ = ros::Time::now(); 95 | last_timestamp_ = start_timestamp_; 96 | 97 | if (publish_cd_) 98 | publishCDEvents(); 99 | 100 | ros::Rate loop_rate(5); 101 | while (ros::ok()) { 102 | if (pub_info_.getNumSubscribers() > 0) { 103 | /** Get and publish camera info **/ 104 | cam_info_msg_.header.stamp = ros::Time::now(); 105 | pub_info_.publish(cam_info_msg_); 106 | } 107 | loop_rate.sleep(); 108 | } 109 | } 110 | 111 | void PropheseeWrapperPublisher::publishCDEvents() { 112 | // Initialize and publish a buffer of CD events 113 | try { 114 | Metavision::CallbackId cd_callback = 115 | camera_.cd().add_callback([this](const Metavision::EventCD *ev_begin, const Metavision::EventCD *ev_end) { 116 | // Check the number of subscribers to the topic 117 | if (pub_cd_events_.getNumSubscribers() <= 0) 118 | return; 119 | 120 | if (ev_begin < ev_end) { 121 | // Compute the current local buffer size with new CD events 122 | const unsigned int buffer_size = ev_end - ev_begin; 123 | 124 | // Get the current time 125 | event_buffer_current_time_.fromNSec(start_timestamp_.toNSec() + (ev_begin->t * 1000.00)); 126 | 127 | /** In case the buffer is empty we set the starting timestamp **/ 128 | if (event_buffer_.empty()) { 129 | // Get starting time 130 | event_buffer_start_time_ = event_buffer_current_time_; 131 | } 132 | 133 | /** Insert the events to the buffer **/ 134 | auto inserter = std::back_inserter(event_buffer_); 135 | 136 | /** When there is not activity filter **/ 137 | std::copy(ev_begin, ev_end, inserter); 138 | 139 | /** Get the last timestamp **/ 140 | event_buffer_current_time_.fromNSec(start_timestamp_.toNSec() + (ev_end - 1)->t * 1000.00); 141 | } 142 | 143 | if ((event_buffer_current_time_ - event_buffer_start_time_) >= event_delta_t_) { 144 | /** Create the message **/ 145 | prophesee_event_msgs::EventArray event_buffer_msg; 146 | 147 | // Sensor geometry in header of the message 148 | event_buffer_msg.header.stamp = event_buffer_current_time_; 149 | event_buffer_msg.height = camera_.geometry().get_height(); 150 | event_buffer_msg.width = camera_.geometry().get_width(); 151 | 152 | /** Set the buffer size for the msg **/ 153 | event_buffer_msg.events.resize(event_buffer_.size()); 154 | 155 | // Copy the events to the ros buffer format 156 | auto buffer_msg_it = event_buffer_msg.events.begin(); 157 | for (const Metavision::EventCD *it = std::addressof(event_buffer_[0]); 158 | it != std::addressof(event_buffer_[event_buffer_.size()]); ++it, ++buffer_msg_it) { 159 | prophesee_event_msgs::Event &event = *buffer_msg_it; 160 | event.x = it->x; 161 | event.y = it->y; 162 | event.polarity = it->p; 163 | event.ts.fromNSec(start_timestamp_.toNSec() + (it->t * 1000.00)); 164 | } 165 | 166 | // Publish the message 167 | pub_cd_events_.publish(event_buffer_msg); 168 | 169 | // Clean the buffer for the next iteration 170 | event_buffer_.clear(); 171 | 172 | ROS_DEBUG("CD data available, buffer size: %d at time: %lui", 173 | static_cast(event_buffer_msg.events.size()), event_buffer_msg.header.stamp.toNSec()); 174 | } 175 | 176 | }); 177 | } catch (Metavision::CameraException &e) { 178 | ROS_WARN("%s", e.what()); 179 | publish_cd_ = false; 180 | } 181 | } 182 | 183 | int main(int argc, char **argv) { 184 | ros::init(argc, argv, "prophesee_ros_publisher"); 185 | 186 | PropheseeWrapperPublisher wp; 187 | wp.startPublishing(); 188 | 189 | ros::shutdown(); 190 | 191 | return 0; 192 | } 193 | -------------------------------------------------------------------------------- /prophesee_ros_driver/src/prophesee_ros_viewer.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************* 2 | * File : prophesee_ros_viewer.cpp * 3 | * * 4 | * Copyright: (c) 2015-2019 Prophesee * 5 | *******************************************************************/ 6 | 7 | #include "prophesee_ros_viewer.h" 8 | 9 | #include 10 | #if CV_MAJOR_VERSION >= 4 11 | #include 12 | #endif 13 | 14 | typedef const boost::function callback; 15 | 16 | PropheseeWrapperViewer::PropheseeWrapperViewer() : 17 | nh_("~"), 18 | cd_window_name_("CD Events"), 19 | display_acc_time_(5000), 20 | initialized_(false) { 21 | std::string camera_name(""); 22 | 23 | // Load Parameters 24 | nh_.getParam("camera_name", camera_name); 25 | nh_.getParam("show_cd", show_cd_); 26 | nh_.getParam("display_accumulation_time", display_acc_time_); 27 | 28 | const std::string topic_cam_info = "/prophesee/" + camera_name + "/camera_info"; 29 | const std::string topic_cd_event_buffer = "/prophesee/" + camera_name + "/cd_events_buffer"; 30 | 31 | // Subscribe to camera info topic 32 | sub_cam_info_ = nh_.subscribe(topic_cam_info, 1, &PropheseeWrapperViewer::cameraInfoCallback, this); 33 | 34 | // Subscribe to CD buffer topic 35 | if (show_cd_) { 36 | callback displayerCDCallback = boost::bind(&CDFrameGenerator::add_events, &cd_frame_generator_, _1); 37 | sub_cd_events_ = nh_.subscribe(topic_cd_event_buffer, 500, displayerCDCallback); 38 | } 39 | } 40 | 41 | PropheseeWrapperViewer::~PropheseeWrapperViewer() { 42 | if (!initialized_) 43 | return; 44 | 45 | // Stop the CD frame generator thread 46 | if (show_cd_) 47 | cd_frame_generator_.stop(); 48 | 49 | // Destroy the windows 50 | cv::destroyAllWindows(); 51 | 52 | nh_.shutdown(); 53 | } 54 | 55 | bool PropheseeWrapperViewer::isInitialized() { 56 | return initialized_; 57 | } 58 | 59 | void PropheseeWrapperViewer::cameraInfoCallback(const sensor_msgs::CameraInfo::ConstPtr &msg) { 60 | if (initialized_) 61 | return; 62 | 63 | if ((msg->width != 0) && (msg->height != 0)) 64 | init(msg->width, msg->height); 65 | } 66 | 67 | bool PropheseeWrapperViewer::init(const unsigned int &sensor_width, const unsigned int &sensor_height) { 68 | if (show_cd_) { 69 | // Define the display window for CD events 70 | create_window(cd_window_name_, sensor_width, sensor_height, 0, 0); 71 | // Initialize CD frame generator 72 | cd_frame_generator_.init(sensor_width, sensor_height); 73 | cd_frame_generator_.set_display_accumulation_time_us(display_acc_time_); 74 | // Start CD frame generator thread 75 | cd_frame_generator_.start(); 76 | } 77 | 78 | initialized_ = true; 79 | 80 | return true; 81 | } 82 | 83 | void PropheseeWrapperViewer::create_window(const std::string &window_name, const unsigned int &sensor_width, 84 | const unsigned int &sensor_height, const int &shift_x, const int &shift_y) { 85 | cv::namedWindow(window_name, CV_GUI_EXPANDED); 86 | cv::resizeWindow(window_name, sensor_width, sensor_height); 87 | // move needs to be after resize on apple, otherwise the window stacks 88 | cv::moveWindow(window_name, shift_x, shift_y); 89 | } 90 | 91 | void PropheseeWrapperViewer::showData() { 92 | if (!show_cd_) 93 | return; 94 | 95 | if (cd_frame_generator_.get_last_ros_timestamp() < ros::Time::now() - ros::Duration(0.5)) { 96 | cd_frame_generator_.reset(); 97 | initialized_ = false; 98 | } 99 | 100 | const auto &cd_frame = cd_frame_generator_.get_current_frame(); 101 | if (!cd_frame.empty()) { 102 | cv::imshow(cd_window_name_, cd_frame); 103 | } 104 | } 105 | 106 | int process_ui_for(const int &delay_ms) { 107 | auto then = std::chrono::high_resolution_clock::now(); 108 | int key = cv::waitKey(delay_ms); 109 | auto now = std::chrono::high_resolution_clock::now(); 110 | // cv::waitKey will not wait if no window is opened, so we wait for him, if needed 111 | std::this_thread::sleep_for(std::chrono::milliseconds( 112 | delay_ms - std::chrono::duration_cast(now - then).count())); 113 | 114 | return key; 115 | } 116 | 117 | int main(int argc, char **argv) { 118 | ros::init(argc, argv, "prophesee_ros_viewer"); 119 | 120 | PropheseeWrapperViewer wv; 121 | 122 | while (ros::ok() && !wv.isInitialized()) { 123 | ros::spinOnce(); 124 | } 125 | 126 | while (ros::ok()) { 127 | ros::spinOnce(); 128 | 129 | wv.showData(); 130 | 131 | process_ui_for(33); 132 | } 133 | 134 | ros::shutdown(); 135 | 136 | return 0; 137 | } 138 | -------------------------------------------------------------------------------- /prophesee_ros_wrapper/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package prophesee_ros_wrapper 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 0.0.2 (2019-10-09) 6 | ------------------ 7 | * Update package.xml 8 | * Contributors: Natalia Lyubova 9 | 10 | 0.0.1 (2019-10-09) 11 | ------------------ 12 | * Initial version 13 | * Contributors: Natalia Lyubova 14 | -------------------------------------------------------------------------------- /prophesee_ros_wrapper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(prophesee_ros_wrapper) 3 | find_package(catkin REQUIRED) 4 | catkin_metapackage() 5 | -------------------------------------------------------------------------------- /prophesee_ros_wrapper/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | prophesee_ros_wrapper 4 | 0.0.2 5 | ROS wrapper for Prophesee event-based sensors 6 | 7 | Natalia Lyubova 8 | Natalia Lyubova 9 | 10 | Apache 2.0 11 | 12 | catkin 13 | 14 | 15 | 16 | 17 | prophesee_event_msgs 18 | prophesee_ros_driver 19 | 20 | 21 | --------------------------------------------------------------------------------