CARLA
 
载入中...
搜索中...
未找到
CarlaLineInvasionPublisher.cpp
浏览该文件的文档.
1#define _GLIBCXX_USE_CXX11_ABI 0
2
4
5#include <string>
6
9
10#include <fastdds/dds/domain/DomainParticipant.hpp>
11#include <fastdds/dds/publisher/Publisher.hpp>
12#include <fastdds/dds/topic/Topic.hpp>
13#include <fastdds/dds/publisher/DataWriter.hpp>
14#include <fastdds/dds/topic/TypeSupport.hpp>
15
16#include <fastdds/dds/domain/qos/DomainParticipantQos.hpp>
17#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
18#include <fastdds/dds/publisher/qos/PublisherQos.hpp>
19#include <fastdds/dds/topic/qos/TopicQos.hpp>
20
21#include <fastrtps/attributes/ParticipantAttributes.h>
22#include <fastrtps/qos/QosPolicies.h>
23#include <fastdds/dds/publisher/qos/DataWriterQos.hpp>
24#include <fastdds/dds/publisher/DataWriterListener.hpp>
25
26// 定义命名空间 carla,可能用于对相关类、函数等进行分类和组织,避免命名冲突
27namespace carla {
28namespace ros2 {
29 // 使用 efd 作为 eprosima::fastdds::dds 命名空间的别名,方便后续代码书写
30 namespace efd = eprosima::fastdds::dds;
31 using erc = eprosima::fastrtps::types::ReturnCode_t;
32 // 定义一个结构体 CarlaLineInvasionPublisherImpl,用于存储与 CarlaLineInvasionPublisher 相关的实现细节和内部状态
34 // 指向领域参与者对象的指针,领域参与者是 DDS 架构中的核心实体,负责协调和管理发布/订阅等操作,初始化为 nullptr
35 efd::DomainParticipant* _participant { nullptr };
36 // 重复定义了,可能是代码冗余,应该删除其中一个
37 efd::DomainParticipant* _participant { nullptr };
38 efd::Publisher* _publisher { nullptr };
39 efd::Topic* _topic { nullptr };
40 efd::DataWriter* _datawriter { nullptr };
42 // CarlaListener 对象,可能用于监听相关事件,具体功能依赖其实现
43 CarlaListener _listener {};
44 // 用于存储要发布的 LaneInvasionEvent 类型的消息对象,初始化为默认状态
46 };
47// CarlaLineInvasionPublisher 类的 Init 函数定义,用于初始化相关的 DDS 实体和配置,返回 true 表示初始化成功,false 表示失败
49 // 首先检查类型支持对象是否为空,如果为空则说明消息类型设置有问题,输出错误信息并返回 false
50 if (_impl->_type == nullptr) {
51 std::cerr << "Invalid TypeSupport" << std::endl;
52 return false;
53 }
54// 获取默认的领域参与者服务质量配置对象,并通过调用其 name 函数设置名称为类中的 _name 成员变量(具体在构造函数中赋值)
55 efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT;
56 pqos.name(_name);
57 // 获取领域参与者工厂的单例实例,用于后续创建领域参与者对象
58 auto factory = efd::DomainParticipantFactory::get_instance();
59 // 使用工厂创建领域参与者对象,传入领域 ID(这里为 0)和服务质量配置对象,如果创建失败则输出错误信息并返回 false
60 _impl->_participant = factory->create_participant(0, pqos);
61 if (_impl->_participant == nullptr) {
62 std::cerr << "Failed to create DomainParticipant" << std::endl;
63 return false;
64 }
65 // 使用创建好的领域参与者对象注册消息类型,确保该类型能在 DDS 系统中被正确识别和处理
66 _impl->_type.register_type(_impl->_participant);
67// 获取默认的发布者服务质量配置对象
68 efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT;
69 // 使用领域参与者对象创建发布者对象,传入服务质量配置和空的监听器指针(可能后续可以添加监听器来监听发布相关事件),如果创建失败则输出错误信息并返回 false
70 _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr);
71 if (_impl->_publisher == nullptr) {
72 std::cerr << "Failed to create Publisher" << std::endl;
73 return false;
74 }
75// 获取默认的主题服务质量配置对象
76 efd::TopicQos tqos = efd::TOPIC_QOS_DEFAULT;
77 const std::string base { "rt/carla/" };
78 std::string topic_name = base;
79 // 如果父名称(_parent)不为空,则将其添加到主题名称中,用于构建更具体的主题路径,增加主题的层次结构和区分度
80 if (!_parent.empty())
81 topic_name += _parent + "/";
82 topic_name += _name;
83 // 使用领域参与者对象创建主题对象,传入主题名称、消息类型名称(通过类型支持对象获取)和服务质量配置对象,如果创建失败则输出错误信息并返回 false
84 _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos);
85 if (_impl->_topic == nullptr) {
86 std::cerr << "Failed to create Topic" << std::endl;
87 return false;
88 }
89// 获取默认的数据写入器服务质量配置对象
90 efd::DataWriterQos wqos = efd::DATAWRITER_QOS_DEFAULT;
91 wqos.endpoint().history_memory_policy = eprosima::fastrtps::rtps::PREALLOCATED_WITH_REALLOC_MEMORY_MODE;
92 efd::DataWriterListener* listener = (efd::DataWriterListener*)_impl->_listener._impl.get();
93 _impl->_datawriter = _impl->_publisher->create_datawriter(_impl->_topic, wqos, listener);
94 if (_impl->_datawriter == nullptr) {
95 std::cerr << "Failed to create DataWriter" << std::endl;
96 return false;
97 }
98 // 设置帧 ID 为类中的名称成员变量(_name),用于标识消息的来源或者所属的帧等相关信息
100 // 如果所有创建和配置操作都成功完成,则返回 true 表示初始化成功
101 return true;
102 }
103// CarlaLineInvasionPublisher 类的 Publish 函数定义,用于将设置好的消息发布出去,返回 true 表示发布成功,false 表示失败
105 // 定义一个实例句柄对象,可能用于标识要写入的消息实例,具体作用依赖 DDS 系统内部机制
106 eprosima::fastrtps::rtps::InstanceHandle_t instance_handle;
107 // 调用数据写入器的 write 方法尝试写入消息,传入要发布的消息对象和实例句柄对象,获取返回的状态码
108 eprosima::fastrtps::types::ReturnCode_t rcode = _impl->_datawriter->write(&_impl->_event, instance_handle);
109 // 根据返回码判断写入操作是否成功,如果返回码是 RETCODE_OK,表示写入成功,返回 true
110 if (rcode == erc::ReturnCodeValue::RETCODE_OK) {
111 return true;
112 }
113 // 如果返回码是 RETCODE_ERROR,表示出现错误,输出错误信息并返回 false
114 if (rcode == erc::ReturnCodeValue::RETCODE_ERROR) {
115 std::cerr << "RETCODE_ERROR" << std::endl;
116 return false;
117 }
118 // 如果返回码是 RETCODE_UNSUPPORTED,表示操作不被支持,输出错误信息并返回 false
119 if (rcode == erc::ReturnCodeValue::RETCODE_UNSUPPORTED) {
120 std::cerr << "RETCODE_UNSUPPORTED" << std::endl;
121 return false;
122 }
123 // 如果返回码是 RETCODE_BAD_PARAMETER,表示参数错误,输出错误信息并返回 false
124 if (rcode == erc::ReturnCodeValue::RETCODE_BAD_PARAMETER) {
125 std::cerr << "RETCODE_BAD_PARAMETER" << std::endl;
126 return false;
127 }
128 // 如果返回码是 RETCODE_PRECONDITION_NOT_MET,表示前置条件未满足,输出错误信息并返回 false
129 if (rcode == erc::ReturnCodeValue::RETCODE_PRECONDITION_NOT_MET) {
130 std::cerr << "RETCODE_PRECONDITION_NOT_MET" << std::endl;
131 return false;
132 }
133 // 如果返回码是 RETCODE_OUT_OF_RESOURCES,表示资源不足,输出错误信息并返回 false
134 if (rcode == erc::ReturnCodeValue::RETCODE_OUT_OF_RESOURCES) {
135 std::cerr << "RETCODE_OUT_OF_RESOURCES" << std::endl;
136 return false;
137 }
138 // 如果返回码是 RETCODE_NOT_ENABLED,表示功能未启用,输出错误信息并返回 false
139 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ENABLED) {
140 std::cerr << "RETCODE_NOT_ENABLED" << std::endl;
141 return false;
142 }
143 // 如果返回码是 RETCODE_IMMUTABLE_POLICY,表示策略不可变,输出错误信息并返回 false
144 if (rcode == erc::ReturnCodeValue::RETCODE_IMMUTABLE_POLICY) {
145 std::cerr << "RETCODE_IMMUTABLE_POLICY" << std::endl;
146 return false;
147 }
148 // 如果返回码是 RETCODE_INCONSISTENT_POLICY,表示策略不一致,输出错误信息并返回 false
149 if (rcode == erc::ReturnCodeValue::RETCODE_INCONSISTENT_POLICY) {
150 std::cerr << "RETCODE_INCONSISTENT_POLICY" << std::endl;
151 return false;
152 }
153 // 如果返回码是 RETCODE_ALREADY_DELETED,表示对象已被删除,输出错误信息并返回 false
154 if (rcode == erc::ReturnCodeValue::RETCODE_ALREADY_DELETED) {
155 std::cerr << "RETCODE_ALREADY_DELETED" << std::endl;
156 return false;
157 }
158 // 如果返回码是 RETCODE_TIMEOUT,表示操作超时,输出错误信息并返回 false
159 if (rcode == erc::ReturnCodeValue::RETCODE_TIMEOUT) {
160 std::cerr << "RETCODE_TIMEOUT" << std::endl;
161 return false;
162 }
163 // 如果返回码是 RETCODE_NO_DATA,表示没有数据,输出错误信息并返回 false
164 if (rcode == erc::ReturnCodeValue::RETCODE_NO_DATA) {
165 std::cerr << "RETCODE_NO_DATA" << std::endl;
166 return false;
167 }
168 // 如果返回码是 RETCODE_ILLEGAL_OPERATION,表示非法操作,输出错误信息并返回 false
169 if (rcode == erc::ReturnCodeValue::RETCODE_ILLEGAL_OPERATION) {
170 std::cerr << "RETCODE_ILLEGAL_OPERATION" << std::endl;
171 return false;
172 }
173 // 如果返回码是 RETCODE_NOT_ALLOWED_BY_SECURITY,表示操作不被安全策略允许,输出错误信息并返回 false
174 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ALLOWED_BY_SECURITY) {
175 std::cerr << "RETCODE_NOT_ALLOWED_BY_SECURITY" << std::endl;
176 return false;
177 }
178 // 如果返回码不属于上述任何已知的情况,则输出 "UNKNOWN" 表示未知错误,并返回 false
179 std::cerr << "UNKNOWN" << std::endl;
180 return false;
181 }
182// CarlaLineInvasionPublisher 类的 SetData 函数定义,用于设置要发布的消息(LaneInvasionEvent 类型)的具体内容
183 void CarlaLineInvasionPublisher::SetData(int32_t seconds, uint32_t nanoseconds, const int32_t* data) {
185 time.sec(seconds);
186 time.nanosec(nanoseconds);
187
188 std_msgs::msg::Header header;
189 header.stamp(std::move(time));
190 header.frame_id(_frame_id);
191
192 _impl->_event.header(std::move(header));
193 _impl->_event.crossed_lane_markings({data[0], data[1], data[2]});
194 }
195// CarlaLineInvasionPublisher 类的构造函数定义,接受 ROS 名称(ros_name)和父名称(parent)作为参数,用于初始化对象的相关属性
196 CarlaLineInvasionPublisher::CarlaLineInvasionPublisher(const char* ros_name, const char* parent) :
197 _impl(std::make_shared<CarlaLineInvasionPublisherImpl>()) {
198 _name = ros_name;
199 _parent = parent;
200 }
201// CarlaLineInvasionPublisher 类的析构函数定义,用于释放对象在生命周期内创建的各种资源,如 DDS 相关实体对象等
203 if (!_impl)
204 return;
205
206 if (_impl->_datawriter)
207 _impl->_publisher->delete_datawriter(_impl->_datawriter);
208
209 if (_impl->_publisher)
210 _impl->_participant->delete_publisher(_impl->_publisher);
211
212 if (_impl->_topic)
213 _impl->_participant->delete_topic(_impl->_topic);
214
215 if (_impl->_participant)
216 efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant);
217 }
218 // CarlaLineInvasionPublisher类的拷贝构造函数,用于创建一个新对象并复制另一个对象的相关成员变量和内部实现对象
225// CarlaLineInvasionPublisher类的拷贝赋值运算符重载函数,用于将一个对象的状态复制到另一个对象
227 _frame_id = other._frame_id;
228 _name = other._name;
229 _parent = other._parent;
230 _impl = other._impl;
231
232 return *this;
233 }
234// CarlaLineInvasionPublisher类的移动构造函数,用于通过移动语义创建新对象,将另一个对象的资源所有权转移过来
236 _frame_id = std::move(other._frame_id);
237 _name = std::move(other._name);
238 _parent = std::move(other._parent);
239 _impl = std::move(other._impl);
240 }
241// CarlaLineInvasionPublisher 类的析构函数定义,用于释放对象在生命周期内创建的各种资源,如 DDS 相关实体对象等
243 _frame_id = std::move(other._frame_id);
244 _name = std::move(other._name);
245 _parent = std::move(other._parent);
246 _impl = std::move(other._impl);
247
248 return *this;
249 }
250}
251}
此类表示用户在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
CarlaLineInvasionPublisher(const char *ros_name="", const char *parent="")
void SetData(int32_t seconds, uint32_t nanoseconds, const int32_t *data)
std::shared_ptr< CarlaLineInvasionPublisherImpl > _impl
CarlaLineInvasionPublisher & operator=(const CarlaLineInvasionPublisher &)
const std::string & parent() const
此类表示用户在IDL文件中定义的LaneInvasionEvent结构。这个类表示在IDL文件中用户定义的LaneInvasionEvent结构,通常用于处理车道入侵相关的消息事件,是整个消息结构体的主...
eprosima::fastrtps::types::ReturnCode_t erc
@using erc
CARLA模拟器的主命名空间。
Definition Carla.cpp:139