CARLA
 
载入中...
搜索中...
未找到
CarlaDVSCameraPublisher.cpp
浏览该文件的文档.
1#define _GLIBCXX_USE_CXX11_ABI 0
2
3#include "CarlaDVSCameraPublisher.h"// 引入CarlaDVS相机发布器的头文件
4
5#include <string>// 引入字符串处理功能
6// 引入CARLA传感器数据中的DVS事件类型
8// 引入CARLA ROS2类型的发布/订阅类型定义
12// 引入CARLA ROS2监听器接口
14// 引入Fast-DDS的域参与者、发布者、主题和数据写入器等核心组件
15#include <fastdds/dds/domain/DomainParticipant.hpp>
16#include <fastdds/dds/publisher/Publisher.hpp>
17#include <fastdds/dds/topic/Topic.hpp>
18#include <fastdds/dds/publisher/DataWriter.hpp>
19#include <fastdds/dds/topic/TypeSupport.hpp>
20// 引入Fast-DDS的QoS策略定义
21#include <fastdds/dds/domain/qos/DomainParticipantQos.hpp>
22#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
23#include <fastdds/dds/publisher/qos/PublisherQos.hpp>
24#include <fastdds/dds/topic/qos/TopicQos.hpp>
25// 引入Fast-RTPS的参与者属性和QoS策略
26#include <fastrtps/attributes/ParticipantAttributes.h>
27#include <fastrtps/qos/QosPolicies.h>
28#include <fastdds/dds/publisher/qos/DataWriterQos.hpp>
29#include <fastdds/dds/publisher/DataWriterListener.hpp>
30
31/**
32 * @namespace carla::ros2
33 * @brief CARLA的ROS2集成命名空间,包含DVS相机、相机信息和点云数据的发布者实现。
34 */
35namespace carla {
36namespace ros2 {
37 /**
38 * @brief 引入Fast-DDS命名空间的别名,简化代码中的引用。
39 */
40 namespace efd = eprosima::fastdds::dds;
41 /**
42 * @brief 引入Fast-RTPS返回代码类型的别名。
43 */
44 using erc = eprosima::fastrtps::types::ReturnCode_t;
45 /**
46 * @struct CarlaDVSCameraPublisherImpl
47 * @brief DVS相机数据发布者的内部实现结构。
48 */
50 /**
51 * @brief Fast-DDS域参与者指针。
52 */
53 efd::DomainParticipant* _participant { nullptr };
54 /**
55 * @brief Fast-DDS发布者指针。
56 */
57 efd::Publisher* _publisher { nullptr };
58 /**
59 * @brief Fast-DDS主题指针。
60 */
61 efd::Topic* _topic { nullptr };
62 /**
63 * @brief Fast-DDS数据写入器指针。
64 */
65 efd::DataWriter* _datawriter { nullptr };
66 /**
67 * @brief Fast-DDS类型支持,用于图像数据。
68 */
69 efd::TypeSupport _type { new sensor_msgs::msg::ImagePubSubType() };
70 /**
71 * @brief CARLA监听器实例,用于处理回调。
72 */
73 CarlaListener _listener {};
74 /**
75 * @brief 待发布的图像数据。
76 */
78 };
79 /**
80 * @struct CarlaCameraInfoPublisherImpl
81 * @brief 相机信息数据发布者的内部实现结构。
82 */
83 struct CarlaCameraInfoPublisherImpl {
84 /**
85 * @brief Fast-DDS域参与者指针。
86 */
87 efd::DomainParticipant* _participant { nullptr };
88 /**
89 * @brief Fast-DDS发布者指针。
90 */
91 efd::Publisher* _publisher { nullptr };
92 /**
93 * @brief Fast-DDS主题指针。
94 */
95 efd::Topic* _topic { nullptr };
96 /**
97 * @brief Fast-DDS数据写入器指针。
98 */
99 efd::DataWriter* _datawriter { nullptr };
100 /**
101 * @brief Fast-DDS类型支持,用于相机信息数据。
102 */
103 efd::TypeSupport _type { new sensor_msgs::msg::CameraInfoPubSubType() };
104 /**
105 * @brief CARLA监听器实例,用于处理回调。
106 */
107 CarlaListener _listener {};
108 /**
109 * @brief 初始化标志。
110 */
111 bool _init {false};
112 /**
113 * @brief 待发布的相机信息数据。
114 */
116 };
117 /**
118 * @struct CarlaPointCloudPublisherImpl
119 * @brief 点云数据发布者的内部实现结构。
120 */
122 /**
123 * @brief Fast-DDS域参与者指针。
124 */
125 efd::DomainParticipant* _participant { nullptr };
126 /**
127 * @brief Fast-DDS发布者指针。
128 */
129 efd::Publisher* _publisher { nullptr };
130 /**
131 * @brief Fast-DDS主题指针。
132 */
133 efd::Topic* _topic { nullptr };
134 /**
135 * @brief Fast-DDS数据写入器指针。
136 */
137 efd::DataWriter* _datawriter { nullptr };
138 /**
139 * @brief Fast-DDS类型支持,用于点云数据。
140 */
142 /**
143 * @brief CARLA监听器实例,用于处理回调。
144 */
145 CarlaListener _listener {};
146 /**
147 * @brief 待发布的点云数据。
148 */
150 };
151 /**
152 * @brief 检查是否已初始化
153 *
154 * @return true 如果已经初始化,否则返回false
155 */
157 return _info->_init;
158 }
159 /**
160 * @brief 初始化相机信息数据
161 *
162 * @param x_offset X轴偏移量
163 * @param y_offset Y轴偏移量
164 * @param height 图像高度
165 * @param width 图像宽度
166 * @param fov 视野角度(以弧度为单位)
167 * @param do_rectify 是否进行校正
168 */
169 void CarlaDVSCameraPublisher::InitInfoData(uint32_t x_offset, uint32_t y_offset, uint32_t height, uint32_t width, float fov, bool do_rectify) {
170 _info->_ci = std::move(sensor_msgs::msg::CameraInfo(height, width, fov));
171 SetInfoRegionOfInterest(x_offset, y_offset, height, width, do_rectify);
172 _info->_init = true;
173 }
174 /**
175 * @brief 初始化CarlaDVSCameraPublisher
176 *
177 * @return true 如果初始化成功,否则返回false
178 */
180 return InitImage() && InitInfo() && InitPointCloud();
181 }
182 /**
183 * @brief 初始化图像发布相关资源
184 *
185 * @return true 如果图像发布初始化成功,否则返回false
186 */
188 if (_impl->_type == nullptr) {
189 std::cerr << "Invalid TypeSupport" << std::endl;
190 return false;
191 }
192
193 efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT;
194 pqos.name(_name);
195 auto factory = efd::DomainParticipantFactory::get_instance();
196 _impl->_participant = factory->create_participant(0, pqos);
197 if (_impl->_participant == nullptr) {
198 std::cerr << "Failed to create DomainParticipant" << std::endl;
199 return false;
200 }
201 _impl->_type.register_type(_impl->_participant);
202
203 efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT;
204 _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr);
205 if (_impl->_publisher == nullptr) {
206 std::cerr << "Failed to create Publisher" << std::endl;
207 return false;
208 }
209
210 efd::TopicQos tqos = efd::TOPIC_QOS_DEFAULT;
211 const std::string publisher_type {"/image"};
212 const std::string base { "rt/carla/" };
213 std::string topic_name = base;
214 if (!_parent.empty())
215 topic_name += _parent + "/";
216 topic_name += _name;
217 topic_name += publisher_type;
218 _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos);
219 if (_impl->_topic == nullptr) {
220 std::cerr << "Failed to create Topic" << std::endl;
221 return false;
222 }
223
224 efd::DataWriterQos wqos = efd::DATAWRITER_QOS_DEFAULT;
225 wqos.endpoint().history_memory_policy = eprosima::fastrtps::rtps::PREALLOCATED_WITH_REALLOC_MEMORY_MODE;
226 efd::DataWriterListener* listener = (efd::DataWriterListener*)_impl->_listener._impl.get();
227 _impl->_datawriter = _impl->_publisher->create_datawriter(_impl->_topic, wqos, listener);
228 if (_impl->_datawriter == nullptr) {
229 std::cerr << "Failed to create DataWriter" << std::endl;
230 return false;
231 }
233 return true;
234 }
235 /**
236 * @brief 初始化相机信息发布相关资源
237 *
238 * @return true 如果相机信息初始化成功,否则返回false
239 */
241 if (_info->_type == nullptr) {
242 std::cerr << "Invalid TypeSupport" << std::endl;
243 return false;
244 }
245 /// 设置DomainParticipant的QoS(Quality of Service)策略为默认值,并设置其名称
246 efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT;
247 pqos.name(_name);
248 /// 获取DomainParticipantFactory的实例
249 auto factory = efd::DomainParticipantFactory::get_instance();
250 _info->_participant = factory->create_participant(0, pqos);
251 /// 创建DomainParticipant
252 if (_info->_participant == nullptr) {
253 /// 如果创建DomainParticipant失败,则输出错误信息并返回false
254 std::cerr << "Failed to create DomainParticipant" << std::endl;
255 return false;
256 }
257 /// 注册数据类型
258 _info->_type.register_type(_info->_participant);
259 /// 设置Publisher的QoS策略为默认值
260 efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT;
261 /// 创建Publisher
262 _info->_publisher = _info->_participant->create_publisher(pubqos, nullptr);
263 if (_info->_publisher == nullptr) {
264 /// 如果创建Publisher失败,则输出错误信息并返回false
265 std::cerr << "Failed to create Publisher" << std::endl;
266 return false;
267 }
268 /// 设置Topic的QoS策略为默认值
269 efd::TopicQos tqos = efd::TOPIC_QOS_DEFAULT;
270 /// 构建Topic的名称
271 const std::string publisher_type {"/camera_info"};
272 const std::string base { "rt/carla/" };
273 std::string topic_name = base;
274 if (!_parent.empty())
275 topic_name += _parent + "/";
276 topic_name += _name;
277 topic_name += publisher_type;
278 /// 创建Topic
279 _info->_topic = _info->_participant->create_topic(topic_name, _info->_type->getName(), tqos);
280 if (_info->_topic == nullptr) {
281 /// 如果创建Topic失败,则输出错误信息并返回false
282 std::cerr << "Failed to create Topic" << std::endl;
283 return false;
284 }
285 /// 设置DataWriter的QoS策略为默认值
286 efd::DataWriterQos wqos = efd::DATAWRITER_QOS_DEFAULT;
287 /// 获取DataWriterListener的实例
288 efd::DataWriterListener* listener = (efd::DataWriterListener*)_info->_listener._impl.get();
289 /// 创建DataWriter
290 _info->_datawriter = _info->_publisher->create_datawriter(_info->_topic, wqos, listener);
291 if (_info->_datawriter == nullptr) {
292 /// 如果创建DataWriter失败,则输出错误信息并返回false
293 std::cerr << "Failed to create DataWriter" << std::endl;
294 return false;
295 }
296 /// 设置帧ID为节点名称
298 /// 所有组件都成功创建,返回true
299 return true;
300 }
301 /**
302 * @brief 初始化点云发布相关资源
303 *
304 * @return true 如果点云初始化成功,否则返回false
305 */
307 if (_point_cloud->_type == nullptr) {
308 std::cerr << "Invalid TypeSupport" << std::endl;
309 return false;
310 }
311 /// 设置DomainParticipant的QoS策略
312 efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT;
313 pqos.name(_name);
314 /// 获取DomainParticipantFactory的实例
315 auto factory = efd::DomainParticipantFactory::get_instance();
316 /// 创建DomainParticipant
317 _point_cloud->_participant = factory->create_participant(0, pqos);
318 if (_point_cloud->_participant == nullptr) {
319 std::cerr << "Failed to create DomainParticipant" << std::endl;
320 return false;
321 }
322 /// 注册类型到DomainParticipant
323 _point_cloud->_type.register_type(_point_cloud->_participant);
324 /// 设置Publisher的QoS策略
325 efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT;
326 _point_cloud->_publisher = _point_cloud->_participant->create_publisher(pubqos, nullptr);
327 if (_point_cloud->_publisher == nullptr) {
328 std::cerr << "Failed to create Publisher" << std::endl;
329 return false;
330 }
331 /// 设置Topic的QoS策略
332 efd::TopicQos tqos = efd::TOPIC_QOS_DEFAULT;
333 const std::string publisher_type {"/point_cloud"};
334 const std::string base { "rt/carla/" };
335 std::string topic_name = base;
336 if (!_parent.empty())
337 topic_name += _parent + "/";
338 topic_name += _name;
339 topic_name += publisher_type;
340 _point_cloud->_topic = _point_cloud->_participant->create_topic(topic_name, _point_cloud->_type->getName(), tqos);
341 if (_point_cloud->_topic == nullptr) {
342 std::cerr << "Failed to create Topic" << std::endl;
343 return false;
344 }
345 /// 设置DataWriter的QoS策略,并指定历史内存策略为预分配并允许重新分配
346 efd::DataWriterQos wqos = efd::DATAWRITER_QOS_DEFAULT;
347 wqos.endpoint().history_memory_policy = eprosima::fastrtps::rtps::PREALLOCATED_WITH_REALLOC_MEMORY_MODE;
348 efd::DataWriterListener* listener = (efd::DataWriterListener*)_point_cloud->_listener._impl.get();
349 _point_cloud->_datawriter = _point_cloud->_publisher->create_datawriter(_point_cloud->_topic, wqos, listener);
350 if (_point_cloud->_datawriter == nullptr) {
351 std::cerr << "Failed to create DataWriter" << std::endl;
352 return false;
353 }
354 /// 设置帧ID为参与者名称
356 return true;
357 }
358 /// @brief 发布图像、信息和点云数据。
359 ///
360 /// 此方法会依次调用 PublishImage()、PublishInfo() 和 PublishPointCloud() 方法,
361 /// 只有当这三个方法都返回 true 时,此方法才返回 true。
362 ///
363 /// @return bool 如果图像、信息和点云数据都成功发布,则返回 true;否则返回 false。
367 /// @brief 发布图像数据。
368 ///
369 /// 使用 DataWriter 将图像数据发布到 DDS 网络中。
370 /// 根据返回的 ReturnCode 判断发布是否成功,并输出相应的错误信息。
371 ///
372 /// @return bool 如果图像数据成功发布,则返回 true;否则返回 false。
374 eprosima::fastrtps::rtps::InstanceHandle_t instance_handle;
375 eprosima::fastrtps::types::ReturnCode_t rcode = _impl->_datawriter->write(& _impl->_image, instance_handle);
376 if (rcode == erc::ReturnCodeValue::RETCODE_OK) {
377 return true;
378 }
379 if (rcode == erc::ReturnCodeValue::RETCODE_ERROR) {
380 std::cerr << "RETCODE_ERROR" << std::endl;
381 return false;
382 }
383 if (rcode == erc::ReturnCodeValue::RETCODE_UNSUPPORTED) {
384 std::cerr << "RETCODE_UNSUPPORTED" << std::endl;
385 return false;
386 }
387 if (rcode == erc::ReturnCodeValue::RETCODE_BAD_PARAMETER) {
388 std::cerr << "RETCODE_BAD_PARAMETER" << std::endl;
389 return false;
390 }
391 if (rcode == erc::ReturnCodeValue::RETCODE_PRECONDITION_NOT_MET) {
392 std::cerr << "RETCODE_PRECONDITION_NOT_MET" << std::endl;
393 return false;
394 }
395 if (rcode == erc::ReturnCodeValue::RETCODE_OUT_OF_RESOURCES) {
396 std::cerr << "RETCODE_OUT_OF_RESOURCES" << std::endl;
397 return false;
398 }
399 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ENABLED) {
400 std::cerr << "RETCODE_NOT_ENABLED" << std::endl;
401 return false;
402 }
403 if (rcode == erc::ReturnCodeValue::RETCODE_IMMUTABLE_POLICY) {
404 std::cerr << "RETCODE_IMMUTABLE_POLICY" << std::endl;
405 return false;
406 }
407 if (rcode == erc::ReturnCodeValue::RETCODE_INCONSISTENT_POLICY) {
408 std::cerr << "RETCODE_INCONSISTENT_POLICY" << std::endl;
409 return false;
410 }
411 if (rcode == erc::ReturnCodeValue::RETCODE_ALREADY_DELETED) {
412 std::cerr << "RETCODE_ALREADY_DELETED" << std::endl;
413 return false;
414 }
415 if (rcode == erc::ReturnCodeValue::RETCODE_TIMEOUT) {
416 std::cerr << "RETCODE_TIMEOUT" << std::endl;
417 return false;
418 }
419 if (rcode == erc::ReturnCodeValue::RETCODE_NO_DATA) {
420 std::cerr << "RETCODE_NO_DATA" << std::endl;
421 return false;
422 }
423 if (rcode == erc::ReturnCodeValue::RETCODE_ILLEGAL_OPERATION) {
424 std::cerr << "RETCODE_ILLEGAL_OPERATION" << std::endl;
425 return false;
426 }
427 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ALLOWED_BY_SECURITY) {
428 std::cerr << "RETCODE_NOT_ALLOWED_BY_SECURITY" << std::endl;
429 return false;
430 }
431 std::cerr << "UNKNOWN" << std::endl;
432 return false;
433 }
434 /// @brief 发布信息数据。
435 ///
436 /// 使用 DataWriter 将信息数据发布到 DDS 网络中。
437 /// 根据返回的 ReturnCode 判断发布是否成功,并输出相应的错误信息。
438 ///
439 /// @return bool 如果信息数据成功发布,则返回 true;否则返回 false。
441 eprosima::fastrtps::rtps::InstanceHandle_t instance_handle;
442 eprosima::fastrtps::types::ReturnCode_t rcode = _info->_datawriter->write(& _info->_ci, instance_handle);
443 if (rcode == erc::ReturnCodeValue::RETCODE_OK) {
444 return true;
445 }
446 if (rcode == erc::ReturnCodeValue::RETCODE_ERROR) {
447 std::cerr << "RETCODE_ERROR" << std::endl;
448 return false;
449 }
450 if (rcode == erc::ReturnCodeValue::RETCODE_UNSUPPORTED) {
451 std::cerr << "RETCODE_UNSUPPORTED" << std::endl;
452 return false;
453 }
454 if (rcode == erc::ReturnCodeValue::RETCODE_BAD_PARAMETER) {
455 std::cerr << "RETCODE_BAD_PARAMETER" << std::endl;
456 return false;
457 }
458 if (rcode == erc::ReturnCodeValue::RETCODE_PRECONDITION_NOT_MET) {
459 std::cerr << "RETCODE_PRECONDITION_NOT_MET" << std::endl;
460 return false;
461 }
462 if (rcode == erc::ReturnCodeValue::RETCODE_OUT_OF_RESOURCES) {
463 std::cerr << "RETCODE_OUT_OF_RESOURCES" << std::endl;
464 return false;
465 }
466 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ENABLED) {
467 std::cerr << "RETCODE_NOT_ENABLED" << std::endl;
468 return false;
469 }
470 if (rcode == erc::ReturnCodeValue::RETCODE_IMMUTABLE_POLICY) {
471 std::cerr << "RETCODE_IMMUTABLE_POLICY" << std::endl;
472 return false;
473 }
474 if (rcode == erc::ReturnCodeValue::RETCODE_INCONSISTENT_POLICY) {
475 std::cerr << "RETCODE_INCONSISTENT_POLICY" << std::endl;
476 return false;
477 }
478 if (rcode == erc::ReturnCodeValue::RETCODE_ALREADY_DELETED) {
479 std::cerr << "RETCODE_ALREADY_DELETED" << std::endl;
480 return false;
481 }
482 if (rcode == erc::ReturnCodeValue::RETCODE_TIMEOUT) {
483 std::cerr << "RETCODE_TIMEOUT" << std::endl;
484 return false;
485 }
486 if (rcode == erc::ReturnCodeValue::RETCODE_NO_DATA) {
487 std::cerr << "RETCODE_NO_DATA" << std::endl;
488 return false;
489 }
490 if (rcode == erc::ReturnCodeValue::RETCODE_ILLEGAL_OPERATION) {
491 std::cerr << "RETCODE_ILLEGAL_OPERATION" << std::endl;
492 return false;
493 }
494 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ALLOWED_BY_SECURITY) {
495 std::cerr << "RETCODE_NOT_ALLOWED_BY_SECURITY" << std::endl;
496 return false;
497 }
498 std::cerr << "UNKNOWN" << std::endl;
499 return false;
500 }
501 /// @brief 发布点云数据。
502 ///
503 /// 使用 DataWriter 将点云数据发布到 DDS 网络中。
504 /// 根据返回的 ReturnCode 判断发布是否成功,并输出相应的错误信息。
505 ///
506 /// @return bool 如果点云数据成功发布,则返回 true;否则返回 false。
508 eprosima::fastrtps::rtps::InstanceHandle_t instance_handle;
509 eprosima::fastrtps::types::ReturnCode_t rcode = _point_cloud->_datawriter->write(&_point_cloud->_pc, instance_handle);
510 if (rcode == erc::ReturnCodeValue::RETCODE_OK) {
511 return true;
512 }
513 if (rcode == erc::ReturnCodeValue::RETCODE_ERROR) {
514 std::cerr << "RETCODE_ERROR" << std::endl;
515 return false;
516 }
517 if (rcode == erc::ReturnCodeValue::RETCODE_UNSUPPORTED) {
518 std::cerr << "RETCODE_UNSUPPORTED" << std::endl;
519 return false;
520 }
521 if (rcode == erc::ReturnCodeValue::RETCODE_BAD_PARAMETER) {
522 std::cerr << "RETCODE_BAD_PARAMETER" << std::endl;
523 return false;
524 }
525 if (rcode == erc::ReturnCodeValue::RETCODE_PRECONDITION_NOT_MET) {
526 std::cerr << "RETCODE_PRECONDITION_NOT_MET" << std::endl;
527 return false;
528 }
529 if (rcode == erc::ReturnCodeValue::RETCODE_OUT_OF_RESOURCES) {
530 std::cerr << "RETCODE_OUT_OF_RESOURCES" << std::endl;
531 return false;
532 }
533 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ENABLED) {
534 std::cerr << "RETCODE_NOT_ENABLED" << std::endl;
535 return false;
536 }
537 if (rcode == erc::ReturnCodeValue::RETCODE_IMMUTABLE_POLICY) {
538 std::cerr << "RETCODE_IMMUTABLE_POLICY" << std::endl;
539 return false;
540 }
541 if (rcode == erc::ReturnCodeValue::RETCODE_INCONSISTENT_POLICY) {
542 std::cerr << "RETCODE_INCONSISTENT_POLICY" << std::endl;
543 return false;
544 }
545 if (rcode == erc::ReturnCodeValue::RETCODE_ALREADY_DELETED) {
546 std::cerr << "RETCODE_ALREADY_DELETED" << std::endl;
547 return false;
548 }
549 if (rcode == erc::ReturnCodeValue::RETCODE_TIMEOUT) {
550 std::cerr << "RETCODE_TIMEOUT" << std::endl;
551 return false;
552 }
553 if (rcode == erc::ReturnCodeValue::RETCODE_NO_DATA) {
554 std::cerr << "RETCODE_NO_DATA" << std::endl;
555 return false;
556 }
557 if (rcode == erc::ReturnCodeValue::RETCODE_ILLEGAL_OPERATION) {
558 std::cerr << "RETCODE_ILLEGAL_OPERATION" << std::endl;
559 return false;
560 }
561 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ALLOWED_BY_SECURITY) {
562 std::cerr << "RETCODE_NOT_ALLOWED_BY_SECURITY" << std::endl;
563 return false;
564 }
565 std::cerr << "UNKNOWN" << std::endl;
566 return false;
567 }
568 /**
569 * @brief 设置图像数据,用于DVS(动态视觉传感器)相机发布者。
570 *
571 * 该函数接收时间戳、图像元素数量、高度、宽度以及图像数据,并将这些数据转换为BGR8格式的图像数据,
572 * 然后调用SetData函数来设置图像数据。
573 *
574 * @param seconds 时间戳的秒部分
575 * @param nanoseconds 时间戳的纳秒部分
576 * @param elements 图像中的事件元素数量
577 * @param height 图像的高度
578 * @param width 图像的宽度
579 * @param data 指向图像数据的指针,数据格式为DVS事件
580 */
581 void CarlaDVSCameraPublisher::SetImageData(int32_t seconds, uint32_t nanoseconds, size_t elements, size_t height, size_t width, const uint8_t* data) {
582 std::vector<uint8_t> im_data;
583 const size_t im_size = width * height * 3;// 计算图像数据的大小(BGR格式)
584 im_data.resize(im_size);// 调整向量大小以适应图像数据
586 for (size_t i = 0; i < elements; ++i, ++vec_event) {
587 // 计算每个事件在图像数据中的索引位置,根据事件的x, y坐标和极性(pol)
588 size_t index = (vec_event->y * width + vec_event->x) * 3 + (static_cast<int>(vec_event->pol) * 2);
589 im_data[index] = 255;// 设置对应位置的像素值为255(假设为亮像素)
590 }
591 // 调用SetData函数来设置图像数据
592 SetData(seconds, nanoseconds, height, width, std::move(im_data));
593 }
594 /**
595 * @brief 设置图像数据,包括时间戳、图像尺寸和图像数据。
596 *
597 * 该函数接收时间戳、图像高度、图像宽度和图像数据,并设置图像消息的相关字段,
598 * 包括时间戳、帧ID、图像尺寸、编码方式以及图像数据。
599 *
600 * @param seconds 时间戳的秒部分
601 * @param nanoseconds 时间戳的纳秒部分
602 * @param height 图像的高度
603 * @param width 图像的宽度
604 * @param data 图像数据的右值引用,用于移动语义
605 */
606 void CarlaDVSCameraPublisher::SetData(int32_t seconds, uint32_t nanoseconds, size_t height, size_t width, std::vector<uint8_t>&& data) {
608 time.sec(seconds);
609 time.nanosec(nanoseconds);
610
611 std_msgs::msg::Header header;
612 header.stamp(std::move(time));// 设置时间戳
613 header.frame_id(_frame_id);// 设置帧ID
614 _impl->_image.header(header);// 设置图像消息的头信息
615 _info->_ci.header(header);// 设置相机信息消息的头信息
616 _point_cloud->_pc.header(header);// 设置点云消息的头信息
617
618 _impl->_image.width(width); // 设置图像宽度
619 _impl->_image.height(height);// 设置图像高度
620 _impl->_image.encoding("bgr8"); //taken from the list of strings in include/sensor_msgs/image_encodings.h // 设置图像编码方式为BGR8
621 _impl->_image.is_bigendian(0);// 设置图像数据是否为大端模式(0表示小端)
622 _impl->_image.step(_impl->_image.width() * sizeof(uint8_t) * 3);// 设置图像每行的字节数
623 _impl->_image.data(std::move(data)); //https://github.com/eProsima/Fast-DDS/issues/2330 // 设置图像数据
624 }
625 /**
626 * @brief 设置相机信息数据的时间戳和帧ID。
627 *
628 * 该函数接收时间戳,并设置相机信息消息的时间戳和帧ID。
629 *
630 * @param seconds 时间戳的秒部分
631 * @param nanoseconds 时间戳的纳秒部分
632 */
633 void CarlaDVSCameraPublisher::SetCameraInfoData(int32_t seconds, uint32_t nanoseconds) {
635 time.sec(seconds);
636 time.nanosec(nanoseconds);
637
638 std_msgs::msg::Header header;
639 header.stamp(std::move(time));// 设置时间戳
640 header.frame_id(_frame_id);// 设置帧ID
641 }
642 /**
643 * @brief 设置相机信息中的感兴趣区域(Region Of Interest, ROI)。
644 *
645 * 该函数用于配置相机信息的ROI,包括x和y偏移量、高度、宽度以及是否进行校正。
646 *
647 * @param x_offset ROI的x轴偏移量。
648 * @param y_offset ROI的y轴偏移量。
649 * @param height ROI的高度。
650 * @param width ROI的宽度。
651 * @param do_rectify 是否对ROI进行校正。
652 */
653 void CarlaDVSCameraPublisher::SetInfoRegionOfInterest( uint32_t x_offset, uint32_t y_offset, uint32_t height, uint32_t width, bool do_rectify) {
655 roi.x_offset(x_offset);
656 roi.y_offset(y_offset);
657 roi.height(height);
658 roi.width(width);
659 roi.do_rectify(do_rectify);
660 _info->_ci.roi(roi);
661 }
662 /**
663 * @brief 设置点云数据。
664 *
665 * 该函数用于配置点云消息,包括高度、宽度、元素数量以及点云数据。
666 *
667 * @param height 点云的高度(即点的行数)。
668 * @param width 点云的宽度(即点的列数)。
669 * @param elements 点云中的元素数量。
670 * @param data 指向点云数据的指针。
671 */
672 void CarlaDVSCameraPublisher::SetPointCloudData(size_t height, size_t width, size_t elements, const uint8_t* data) {
673
674 std::vector<uint8_t> vector_data;
675 const size_t size = height * width;// 计算点云数据所需的总字节数
676 vector_data.resize(size);// 调整向量大小以适应点云数据
677 std::memcpy(&vector_data[0], &data[0], size);// 将原始数据复制到向量中
678 // 配置点云描述符(即点的属性信息)
680 descriptor1.name("x");
681 descriptor1.offset(0);
683 descriptor1.count(1);
685 descriptor2.name("y");
686 descriptor2.offset(2);
688 descriptor2.count(1);
690 descriptor3.name("t");
691 descriptor3.offset(4);
693 descriptor3.count(1);
695 descriptor3.name("pol");
696 descriptor3.offset(12);
698 descriptor3.count(1);
699
700 const size_t point_size = sizeof(carla::sensor::data::DVSEvent);// 假设每个点的大小与DVSEvent结构相同
701 _point_cloud->_pc.width(width); // 设置点云的宽度
702 _point_cloud->_pc.height(height);// 设置点云的高度
703 _point_cloud->_pc.is_bigendian(false);// 设置点云数据是否为大端模式(这里假设为小端)
704 _point_cloud->_pc.fields({descriptor1, descriptor2, descriptor3, descriptor4});// 设置点云的描述符
705 _point_cloud->_pc.point_step(point_size);// 设置每个点的步长(即每个点的大小)
706 _point_cloud->_pc.row_step(width * point_size);// 设置每行的步长(即每行数据的大小)
707 _point_cloud->_pc.is_dense(false);// 设置点云是否为稠密点云(false表示存在无效点)
708 _point_cloud->_pc.data(std::move(vector_data));// 设置点云数据(使用移动语义)
709 }
710 /**
711 * @brief CarlaDVSCameraPublisher的构造函数。
712 *
713 * 初始化CarlaDVSCameraPublisher对象,包括内部实现对象、相机信息发布者对象和点云发布者对象。
714 *
715 * @param ros_name ROS节点名称。
716 * @param parent 父节点或相关实体的名称。
717 */
718 CarlaDVSCameraPublisher::CarlaDVSCameraPublisher(const char* ros_name, const char* parent) :
719 _impl(std::make_shared<CarlaDVSCameraPublisherImpl>()),
720 _info(std::make_shared<CarlaCameraInfoPublisherImpl>()),
721 _point_cloud(std::make_shared<CarlaPointCloudPublisherImpl>()) {
722 _name = ros_name;
723 _parent = parent;
724 }
725 /**
726 * @brief CarlaDVSCameraPublisher的析构函数。
727 *
728 * 清理CarlaDVSCameraPublisher对象,包括释放内部实现对象、相机信息发布者对象和点云发布者对象所占用的资源。
729 */
731 if (!_impl)
732 return;
733
734 if (_impl->_datawriter)
735 _impl->_publisher->delete_datawriter(_impl->_datawriter);
736
737 if (_impl->_publisher)
738 _impl->_participant->delete_publisher(_impl->_publisher);
739
740 if (_impl->_topic)
741 _impl->_participant->delete_topic(_impl->_topic);
742
743 if (_impl->_participant)
744 efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant);
745
746 if (!_info)
747 return;
748
749 if (_info->_datawriter)
750 _info->_publisher->delete_datawriter(_info->_datawriter);
751
752 if (_info->_publisher)
753 _info->_participant->delete_publisher(_info->_publisher);
754
755 if (_info->_topic)
756 _info->_participant->delete_topic(_info->_topic);
757
758 if (_info->_participant)
759 efd::DomainParticipantFactory::get_instance()->delete_participant(_info->_participant);
760
761 if (!_point_cloud)
762 return;
763
764 if (_point_cloud->_datawriter)
765 _point_cloud->_publisher->delete_datawriter(_point_cloud->_datawriter);
766
767 if (_point_cloud->_publisher)
768 _point_cloud->_participant->delete_publisher(_point_cloud->_publisher);
769
770 if (_point_cloud->_topic)
771 _point_cloud->_participant->delete_topic(_point_cloud->_topic);
772
773 if (_point_cloud->_participant)
774 efd::DomainParticipantFactory::get_instance()->delete_participant(_point_cloud->_participant);
775 }
776 /**
777 * @brief CarlaDVSCameraPublisher的拷贝构造函数。
778 *
779 * 创建一个新的CarlaDVSCameraPublisher对象,并复制另一个CarlaDVSCameraPublisher对象的成员变量。
780 *
781 * @param other 要复制的CarlaDVSCameraPublisher对象。
782 */
784 _frame_id = other._frame_id;
785 _name = other._name;
786 _parent = other._parent;
787 _impl = other._impl;
788 _info = other._info;
790 }
791 /**
792 * @brief 赋值运算符重载。
793 *
794 * 将另一个CarlaDVSCameraPublisher对象的成员变量赋值给当前对象。
795 *
796 * @param other 要赋值的CarlaDVSCameraPublisher对象。
797 * @return 返回对当前对象的引用。
798 */
800 _frame_id = other._frame_id;
801 _name = other._name;
802 _parent = other._parent;
803 _impl = other._impl;
804 _info = other._info;
806
807 return *this;
808 }
809 /**
810 * @brief CarlaDVSCameraPublisher的移动构造函数。
811 *
812 * 创建一个新的CarlaDVSCameraPublisher对象,并移动另一个CarlaDVSCameraPublisher对象的成员变量。
813 *
814 * @param other 要移动的CarlaDVSCameraPublisher对象。
815 */
817 _frame_id = std::move(other._frame_id);
818 _name = std::move(other._name);
819 _parent = std::move(other._parent);
820 _impl = std::move(other._impl);
821 _info = std::move(other._info);
822 _point_cloud = std::move(other._point_cloud);
823 }
824 /**
825 * @brief 移动赋值运算符重载。
826 *
827 * 将另一个CarlaDVSCameraPublisher对象的成员变量移动到当前对象。
828 *
829 * @param other 要移动的CarlaDVSCameraPublisher对象。
830 * @return 返回对当前对象的引用。
831 */
833 _frame_id = std::move(other._frame_id);
834 _name = std::move(other._name);
835 _parent = std::move(other._parent);
836 _impl = std::move(other._impl);
837 _info = std::move(other._info);
838 _point_cloud = std::move(other._point_cloud);
839
840 return *this;
841 }
842}
843}
此类表示用户在IDL文件中定义的Time结构。
eProsima_user_DllExport void nanosec(uint32_t _nanosec)
此函数设置成员nanosec的值。
Definition Time.cpp:183
eProsima_user_DllExport void sec(int32_t _sec)
此函数设置成员sec的值。
Definition Time.cpp:152
void SetPointCloudData(size_t height, size_t width, size_t elements, const uint8_t *data)
设置点云数据。
CarlaDVSCameraPublisher & operator=(const CarlaDVSCameraPublisher &)
赋值运算符重载。
CarlaDVSCameraPublisher(const char *ros_name="", const char *parent="")
CarlaDVSCameraPublisher的构造函数。
std::shared_ptr< CarlaCameraInfoPublisherImpl > _info
std::shared_ptr< CarlaDVSCameraPublisherImpl > _impl
bool Publish()
发布图像、信息和点云数据。
void SetImageData(int32_t seconds, uint32_t nanoseconds, size_t elements, size_t height, size_t width, const uint8_t *data)
设置图像数据,用于DVS(动态视觉传感器)相机发布者。
void InitInfoData(uint32_t x_offset, uint32_t y_offset, uint32_t height, uint32_t width, float fov, bool do_rectify)
初始化相机信息数据
bool InitPointCloud()
初始化点云发布相关资源
void SetCameraInfoData(int32_t seconds, uint32_t nanoseconds)
设置相机信息数据的时间戳和帧ID。
bool InitInfo()
初始化相机信息发布相关资源
bool InitImage()
初始化图像发布相关资源
bool HasBeenInitialized() const
检查是否已初始化
void SetData(int32_t seconds, uint32_t nanoseconds, size_t height, size_t width, std::vector< uint8_t > &&data)
设置图像数据,包括时间戳、图像尺寸和图像数据。
void SetInfoRegionOfInterest(uint32_t x_offset, uint32_t y_offset, uint32_t height, uint32_t width, bool do_rectify)
设置相机信息中的感兴趣区域(Region Of Interest, ROI)。
bool Init()
初始化CarlaDVSCameraPublisher
std::shared_ptr< CarlaPointCloudPublisherImpl > _point_cloud
~CarlaDVSCameraPublisher()
CarlaDVSCameraPublisher的析构函数。
const std::string & parent() const
此类表示用户在 IDL 文件中定义的 CameraInfo 类型的 TopicDataType。 <>
This class represents the structure CameraInfo defined by the user in the IDL file....
Definition CameraInfo.h:75
此类表示用户在IDL文件中定义的Image类型的主题数据类型。
This class represents the structure Image defined by the user in the IDL file.这个类表示在 IDL(接口定义语言)文件中由用...
This class represents the TopicDataType of the type PointCloud2 defined by the user in the IDL file.
This class represents the structure PointCloud2 defined by the user in the IDL file.
Definition PointCloud2.h:74
此类表示用户在 IDL 文件中定义的结构 PointField。 <>
Definition PointField.h:79
eProsima_user_DllExport void count(uint32_t _count)
此函数设置成员 count 的值
eProsima_user_DllExport void offset(uint32_t _offset)
此函数设置成员 offset 的值
eProsima_user_DllExport void name(const std::string &_name)
此函数复制成员 name 的值
eProsima_user_DllExport void datatype(uint8_t _datatype)
此函数设置成员 datatype 的值
This class represents the structure RegionOfInterest defined by the user in the IDL file.
eProsima_user_DllExport void y_offset(uint32_t _y_offset)
This function sets a value in member y_offset
eProsima_user_DllExport void width(uint32_t _width)
This function sets a value in member width
eProsima_user_DllExport void height(uint32_t _height)
This function sets a value in member height
eProsima_user_DllExport void x_offset(uint32_t _x_offset)
This function sets a value in member x_offset
eProsima_user_DllExport void do_rectify(bool _do_rectify)
This function sets a value in member do_rectify
eprosima::fastrtps::types::ReturnCode_t erc
@using erc
CARLA模拟器的主命名空间。
Definition Carla.cpp:139
const uint8_t PointField__UINT16
Definition PointField.h:68
const uint8_t PointField__INT8
Definition PointField.h:65
const uint8_t PointField__FLOAT64
Definition PointField.h:72
Carla相机信息发布者内部实现的结构体。
efd::DomainParticipant * _participant
DDS域参与者指针。
efd::TypeSupport _type
DDS类型支持,用于相机信息消息。
efd::DataWriter * _datawriter
DDS数据写入器指针。
efd::Publisher * _publisher
DDS发布者指针。
sensor_msgs::msg::CameraInfo _ci
待发布的相机信息数据。
CarlaListener _listener
CARLA监听器实例。
DVS相机数据发布者的内部实现结构。
efd::Topic * _topic
Fast-DDS主题指针。
sensor_msgs::msg::Image _image
待发布的图像数据。
efd::TypeSupport _type
Fast-DDS类型支持,用于图像数据。
efd::DataWriter * _datawriter
Fast-DDS数据写入器指针。
efd::DomainParticipant * _participant
Fast-DDS域参与者指针。
CarlaListener _listener
CARLA监听器实例,用于处理回调。
efd::Publisher * _publisher
Fast-DDS发布者指针。
点云数据发布者的内部实现结构。
efd::DataWriter * _datawriter
Fast-DDS数据写入器指针。
CarlaListener _listener
CARLA监听器实例,用于处理回调。
efd::TypeSupport _type
Fast-DDS类型支持,用于点云数据。
efd::Publisher * _publisher
Fast-DDS发布者指针。
efd::DomainParticipant * _participant
Fast-DDS域参与者指针。
sensor_msgs::msg::PointCloud2 _pc
待发布的点云数据。