├── .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 | 
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 |
--------------------------------------------------------------------------------