1#define _GLIBCXX_USE_CXX11_ABI 0
12#include <fastdds/dds/domain/DomainParticipant.hpp>
13#include <fastdds/dds/publisher/Publisher.hpp>
14#include <fastdds/dds/topic/Topic.hpp>
15#include <fastdds/dds/publisher/DataWriter.hpp>
16#include <fastdds/dds/topic/TypeSupport.hpp>
18#include <fastdds/dds/domain/qos/DomainParticipantQos.hpp>
19#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
20#include <fastdds/dds/publisher/qos/PublisherQos.hpp>
21#include <fastdds/dds/topic/qos/TopicQos.hpp>
23#include <fastrtps/attributes/ParticipantAttributes.h>
24#include <fastrtps/qos/QosPolicies.h>
25#include <fastdds/dds/publisher/qos/DataWriterQos.hpp>
26#include <fastdds/dds/publisher/DataWriterListener.hpp>
36template <
typename T> T
CLAMP(
const T& value,
const T& low,
const T& high)
38 return value < low ? low : (value > high ? high : value);
53 namespace efd = eprosima::fastdds::dds;
57 using erc = eprosima::fastrtps::types::ReturnCode_t;
77 struct CarlaCameraInfoPublisherImpl {
80 efd::Topic*
_topic {
nullptr };
128 if (
_impl->_type ==
nullptr) {
129 std::cerr <<
"Invalid TypeSupport" << std::endl;
133 efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT;
136 auto factory = efd::DomainParticipantFactory::get_instance();
138 _impl->_participant = factory->create_participant(0, pqos);
139 if (
_impl->_participant ==
nullptr) {
141 std::cerr <<
"Failed to create DomainParticipant" << std::endl;
145 _impl->_type.register_type(
_impl->_participant);
147 efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT;
149 _impl->_publisher =
_impl->_participant->create_publisher(pubqos,
nullptr);
150 if (
_impl->_publisher ==
nullptr) {
152 std::cerr <<
"Failed to create Publisher" << std::endl;
156 efd::TopicQos tqos = efd::TOPIC_QOS_DEFAULT;
158 const std::string publisher_type {
"/image"};
159 const std::string base {
"rt/carla/" };
160 std::string topic_name = base;
164 topic_name += publisher_type;
166 _impl->_topic =
_impl->_participant->create_topic(topic_name,
_impl->_type->getName(), tqos);
167 if (
_impl->_topic ==
nullptr) {
169 std::cerr <<
"Failed to create Topic" << std::endl;
173 efd::DataWriterQos wqos = efd::DATAWRITER_QOS_DEFAULT;
174 wqos.endpoint().history_memory_policy = eprosima::fastrtps::rtps::PREALLOCATED_WITH_REALLOC_MEMORY_MODE;
178 _impl->_datawriter =
_impl->_publisher->create_datawriter(
_impl->_topic, wqos, listener);
179 if (
_impl->_datawriter ==
nullptr) {
181 std::cerr <<
"Failed to create DataWriter" << std::endl;
202 std::cerr <<
"Invalid TypeSupport" << std::endl;
208 efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT;
210 auto factory = efd::DomainParticipantFactory::get_instance();
211 _impl_info->_participant = factory->create_participant(0, pqos);
216 std::cerr <<
"Failed to create DomainParticipant" << std::endl;
226 efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT;
232 std::cerr <<
"Failed to create Publisher" << std::endl;
238 efd::TopicQos tqos = efd::TOPIC_QOS_DEFAULT;
239 const std::string publisher_type {
"/camera_info"};
240 const std::string base {
"rt/carla/" };
241 std::string topic_name = base;
245 topic_name += publisher_type;
251 std::cerr <<
"Failed to create Topic" << std::endl;
257 efd::DataWriterQos wqos = efd::DATAWRITER_QOS_DEFAULT;
264 std::cerr <<
"Failed to create DataWriter" << std::endl;
292 eprosima::fastrtps::rtps::InstanceHandle_t instance_handle;
296 eprosima::fastrtps::types::ReturnCode_t rcode =
_impl->_datawriter->write(&
_impl->_image, instance_handle);
300 if (rcode == erc::ReturnCodeValue::RETCODE_OK) {
304 if (rcode == erc::ReturnCodeValue::RETCODE_ERROR) {
306 std::cerr <<
"RETCODE_ERROR" << std::endl;
309 if (rcode == erc::ReturnCodeValue::RETCODE_UNSUPPORTED) {
311 std::cerr <<
"RETCODE_UNSUPPORTED" << std::endl;
314 if (rcode == erc::ReturnCodeValue::RETCODE_BAD_PARAMETER) {
316 std::cerr <<
"RETCODE_BAD_PARAMETER" << std::endl;
319 if (rcode == erc::ReturnCodeValue::RETCODE_PRECONDITION_NOT_MET) {
321 std::cerr <<
"RETCODE_PRECONDITION_NOT_MET" << std::endl;
324 if (rcode == erc::ReturnCodeValue::RETCODE_OUT_OF_RESOURCES) {
326 std::cerr <<
"RETCODE_OUT_OF_RESOURCES" << std::endl;
329 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ENABLED) {
331 std::cerr <<
"RETCODE_NOT_ENABLED" << std::endl;
334 if (rcode == erc::ReturnCodeValue::RETCODE_IMMUTABLE_POLICY) {
336 std::cerr <<
"RETCODE_IMMUTABLE_POLICY" << std::endl;
339 if (rcode == erc::ReturnCodeValue::RETCODE_INCONSISTENT_POLICY) {
341 std::cerr <<
"RETCODE_INCONSISTENT_POLICY" << std::endl;
344 if (rcode == erc::ReturnCodeValue::RETCODE_ALREADY_DELETED) {
346 std::cerr <<
"RETCODE_ALREADY_DELETED" << std::endl;
349 if (rcode == erc::ReturnCodeValue::RETCODE_TIMEOUT) {
351 std::cerr <<
"RETCODE_TIMEOUT" << std::endl;
354 if (rcode == erc::ReturnCodeValue::RETCODE_NO_DATA) {
356 std::cerr <<
"RETCODE_NO_DATA" << std::endl;
359 if (rcode == erc::ReturnCodeValue::RETCODE_ILLEGAL_OPERATION) {
361 std::cerr <<
"RETCODE_ILLEGAL_OPERATION" << std::endl;
364 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ALLOWED_BY_SECURITY) {
366 std::cerr <<
"RETCODE_NOT_ALLOWED_BY_SECURITY" << std::endl;
370 std::cerr <<
"UNKNOWN" << std::endl;
384 eprosima::fastrtps::rtps::InstanceHandle_t instance_handle;
387 eprosima::fastrtps::types::ReturnCode_t rcode =
_impl_info->_datawriter->write(&
_impl_info->_info, instance_handle);
389 if (rcode == erc::ReturnCodeValue::RETCODE_OK) {
393 if (rcode == erc::ReturnCodeValue::RETCODE_ERROR) {
395 std::cerr <<
"RETCODE_ERROR" << std::endl;
398 if (rcode == erc::ReturnCodeValue::RETCODE_UNSUPPORTED) {
400 std::cerr <<
"RETCODE_UNSUPPORTED" << std::endl;
403 if (rcode == erc::ReturnCodeValue::RETCODE_BAD_PARAMETER) {
405 std::cerr <<
"RETCODE_BAD_PARAMETER" << std::endl;
408 if (rcode == erc::ReturnCodeValue::RETCODE_PRECONDITION_NOT_MET) {
410 std::cerr <<
"RETCODE_PRECONDITION_NOT_MET" << std::endl;
413 if (rcode == erc::ReturnCodeValue::RETCODE_OUT_OF_RESOURCES) {
415 std::cerr <<
"RETCODE_OUT_OF_RESOURCES" << std::endl;
418 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ENABLED) {
420 std::cerr <<
"RETCODE_NOT_ENABLED" << std::endl;
423 if (rcode == erc::ReturnCodeValue::RETCODE_IMMUTABLE_POLICY) {
425 std::cerr <<
"RETCODE_IMMUTABLE_POLICY" << std::endl;
428 if (rcode == erc::ReturnCodeValue::RETCODE_INCONSISTENT_POLICY) {
430 std::cerr <<
"RETCODE_INCONSISTENT_POLICY" << std::endl;
433 if (rcode == erc::ReturnCodeValue::RETCODE_ALREADY_DELETED) {
435 std::cerr <<
"RETCODE_ALREADY_DELETED" << std::endl;
438 if (rcode == erc::ReturnCodeValue::RETCODE_TIMEOUT) {
440 std::cerr <<
"RETCODE_TIMEOUT" << std::endl;
443 if (rcode == erc::ReturnCodeValue::RETCODE_NO_DATA) {
445 std::cerr <<
"RETCODE_NO_DATA" << std::endl;
448 if (rcode == erc::ReturnCodeValue::RETCODE_ILLEGAL_OPERATION) {
450 std::cerr <<
"RETCODE_ILLEGAL_OPERATION" << std::endl;
453 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ALLOWED_BY_SECURITY) {
455 std::cerr <<
"RETCODE_NOT_ALLOWED_BY_SECURITY" << std::endl;
458 std::cerr <<
"UNKNOWN" << std::endl;
475 constexpr float pi = 3.1415f;
476 constexpr float rad2ang = 360.0f/(2.0f*pi);
478 const size_t max_index = width * height * 2;
480 std::vector<uint8_t> vector_data;
482 vector_data.resize(height * width * 4);
484 size_t data_index = 0;
486 for (
size_t index = 0; index < max_index; index += 2) {
488 const float vx = data[index];
489 const float vy = data[index + 1];
491 float angle = 180.0f + std::atan2(vy, vx) * rad2ang;
494 angle = 360.0f + angle;
496 angle = std::fmod(angle, 360.0f);
498 const float norm = std::sqrt(vx * vx + vy * vy);
500 const float shift = 0.999f;
501 const float a = 1.0f / std::log(0.1f + shift);
502 const float intensity = CLAMP<float>(a * std::log(norm + shift), 0.0f, 1.0f);
504 const float& H = angle;
505 const float S = 1.0f;
506 const float V = intensity;
508 const float H_60 = H * (1.0f / 60.0f);
510 const float C = V * S;
511 const float X = C * (1.0f - std::abs(std::fmod(H_60, 2.0f) - 1.0f));
512 const float m = V - C;
517 const unsigned int angle_case =
static_cast<const unsigned int>(H_60);
518 switch (angle_case) {
556 const uint8_t
R =
static_cast<uint8_t
>((r + m) * 255.0f);
557 const uint8_t G =
static_cast<uint8_t
>((g + m) * 255.0f);
558 const uint8_t B =
static_cast<uint8_t
>((b + m) * 255.0f);
561 vector_data[data_index++] = B;
562 vector_data[data_index++] = G;
563 vector_data[data_index++] =
R;
564 vector_data[data_index++] = 0;
567 SetData(seconds, nanoseconds, height, width, std::move(vector_data));
607 std_msgs::msg::Header header;
608 header.stamp(std::move(time));
611 _impl->_image.header(std::move(header));
612 _impl->_image.width(width);
613 _impl->_image.height(height);
614 _impl->_image.encoding(
"bgra8");
615 _impl->_image.is_bigendian(0);
616 _impl->_image.step(
_impl->_image.width() *
sizeof(uint8_t) * 4);
617 _impl->_image.data(std::move(data));
632 std_msgs::msg::Header header;
633 header.stamp(std::move(time));
660 if (
_impl->_datawriter)
661 _impl->_publisher->delete_datawriter(
_impl->_datawriter);
663 if (
_impl->_publisher)
664 _impl->_participant->delete_publisher(
_impl->_publisher);
667 _impl->_participant->delete_topic(
_impl->_topic);
669 if (
_impl->_participant)
670 efd::DomainParticipantFactory::get_instance()->delete_participant(
_impl->_participant);
685 efd::DomainParticipantFactory::get_instance()->delete_participant(
_impl_info->_participant);
726 _name = std::move(other._name);
727 _parent = std::move(other._parent);
728 _impl = std::move(other._impl);
742 _name = std::move(other._name);
743 _parent = std::move(other._parent);
744 _impl = std::move(other._impl);
T CLAMP(const T &value, const T &low, const T &high)
通用CLAMP函数,用于将值限制在指定范围内。
carla::rpc::Response< T > R
eProsima_user_DllExport void nanosec(uint32_t _nanosec)
此函数设置成员nanosec的值。
eProsima_user_DllExport void sec(int32_t _sec)
此函数设置成员sec的值。
void InitInfoData(uint32_t x_offset, uint32_t y_offset, uint32_t height, uint32_t width, float fov, bool do_rectify)
初始化摄像头信息数据。
CarlaOpticalFlowCameraPublisher & operator=(const CarlaOpticalFlowCameraPublisher &)
赋值运算符重载
void SetImageData(int32_t seconds, uint32_t nanoseconds, size_t height, size_t width, const float *data)
设置图像数据,将光学流数据转换为RGBA图像数据
void SetInfoRegionOfInterest(uint32_t x_offset, uint32_t y_offset, uint32_t height, uint32_t width, bool do_rectify)
设置感兴趣区域(ROI)信息
bool InitImage()
初始化图像相关的资源。
bool HasBeenInitialized() const
检查类是否已经被初始化。
void SetCameraInfoData(int32_t seconds, uint32_t nanoseconds)
设置相机信息数据的时间戳
bool InitInfo()
初始化信息并设置CarlaOpticalFlowCameraPublisher的相关参数。
bool PublishImage()
发布图像数据。
CarlaOpticalFlowCameraPublisher(const char *ros_name="", const char *parent="")
CarlaOpticalFlowCameraPublisher类的构造函数
void SetData(int32_t seconds, uint32_t nanoseconds, size_t height, size_t width, std::vector< uint8_t > &&data)
设置图像数据
std::shared_ptr< CarlaOpticalFlowCameraPublisherImpl > _impl
~CarlaOpticalFlowCameraPublisher()
CarlaOpticalFlowCameraPublisher类的析构函数
std::shared_ptr< CarlaCameraInfoPublisherImpl > _impl_info
const std::string & parent() const
此类表示用户在 IDL 文件中定义的 CameraInfo 类型的 TopicDataType。 <>
This class represents the structure CameraInfo defined by the user in the IDL file....
此类表示用户在IDL文件中定义的Image类型的主题数据类型。
This class represents the structure Image defined by the user in the IDL file.这个类表示在 IDL(接口定义语言)文件中由用...
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
sensor_msgs::msg::CameraInfo _info
相机信息消息实例。
efd::DomainParticipant * _participant
DDS域参与者指针。
efd::TypeSupport _type
DDS类型支持,用于相机信息消息。
efd::Topic * _topic
DDS主题指针。
efd::DataWriter * _datawriter
DDS数据写入器指针。
efd::Publisher * _publisher
DDS发布者指针。
CarlaListener _listener
CARLA监听器实例。
sensor_msgs::msg::Image _image
存储待发布的图像数据。
efd::DomainParticipant * _participant
域参与者,用于创建其他DDS实体。
efd::Publisher * _publisher
发布者,用于发送数据。
efd::TypeSupport _type
类型支持,用于序列化和反序列化图像数据。
efd::Topic * _topic
主题,定义了发布的数据类型。
efd::DataWriter * _datawriter
数据写入器,用于将数据写入主题。
CarlaListener _listener
Carla监听器,可能用于接收相关事件或数据。