CARLA
 
载入中...
搜索中...
未找到
CarlaCollisionPublisher.cpp
浏览该文件的文档.
1#define _GLIBCXX_USE_CXX11_ABI 0
2
3#include "CarlaCollisionPublisher.h"// 包含Carla碰撞事件发布者类的声明
4
5#include <string>// 包含字符串处理相关的功能
6// 包含Carla ROS 2类型定义和监听器相关的头文件
9// 包含Fast-DDS(eProsima Fast RTPS的C++ API)相关的头文件
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// 包含Fast-DDS QOS策略相关的头文件
16#include <fastdds/dds/domain/qos/DomainParticipantQos.hpp> // 包含域参与者QOS策略相关的类
17#include <fastdds/dds/domain/DomainParticipantFactory.hpp>// 包含域参与者工厂相关的类
18#include <fastdds/dds/publisher/qos/PublisherQos.hpp>// 包含发布者QOS策略相关的类
19#include <fastdds/dds/topic/qos/TopicQos.hpp>// 包含主题QOS策略相关的类
20// 包含Fast RTPS属性相关的头文件
21#include <fastrtps/attributes/ParticipantAttributes.h>// 包含参与者属性相关的类
22#include <fastrtps/qos/QosPolicies.h>// 包含QOS策略相关的类
23// 包含Fast-DDS数据写入器QOS策略和监听器相关的头文件
24#include <fastdds/dds/publisher/qos/DataWriterQos.hpp>// 包含数据写入器QOS策略相关的类
25#include <fastdds/dds/publisher/DataWriterListener.hpp>// 包含数据写入器监听器相关的类
26
27/**
28 * @namespace carla::ros2
29 * @brief 命名空间,用于组织CARLA与ROS2相关的代码。
30 */
31
32 /**
33 * @brief 命名空间别名定义
34 * @details 为eprosima::fastdds::dds命名空间定义别名efd,为eprosima::fastrtps::types::ReturnCode_t类型定义别名erc,方便后续使用。
35 */
36namespace carla {
37namespace ros2 {
38
39 namespace efd = eprosima::fastdds::dds;
40 using erc = eprosima::fastrtps::types::ReturnCode_t;
41 /**
42 * @struct CarlaCollisionPublisherImpl
43 * @brief CarlaCollisionPublisher的内部实现结构体
44 *
45 * 该结构体包含了与DDS通信相关的成员变量,用于管理CARLA碰撞事件的发布。
46 */
48 /**
49 * @brief DDS域参与者指针
50 * @details 指向一个DDS域参与者的指针,用于管理通信域。
51 */
52 efd::DomainParticipant* _participant { nullptr };
53 /**
54 * @brief DDS发布者指针
55 * @details 指向一个DDS发布者的指针,用于发布消息。
56 */
57 efd::Publisher* _publisher { nullptr };
58 /**
59 * @brief DDS主题指针
60 * @details 指向一个DDS主题的指针,用于定义消息的类型和名称。
61 */
62 efd::Topic* _topic { nullptr };
63 /**
64 * @brief DDS数据写入器指针
65 * @details 指向一个DDS数据写入器的指针,用于写入数据到主题。
66 */
67 efd::DataWriter* _datawriter { nullptr };
68 /**
69 * @brief DDS类型支持
70 * @details 用于注册和管理消息类型的支持对象,这里使用carla_msgs::msg::CarlaCollisionEventPubSubType。
71 */
73 /**
74 * @brief Carla监听器
75 * @details 用于监听DDS通信事件的监听器对象。
76 */
77 CarlaListener _listener {};
78 /**
79 * @brief CARLA碰撞事件消息
80 * @details 存储要发布的CARLA碰撞事件消息的数据结构。
81 */
82 carla_msgs::msg::CarlaCollisionEvent _event {};
83 };
84 /**
85 * @brief 初始化CarlaCollisionPublisher
86 * @return bool 初始化成功返回true,失败返回false
87 *
88 * 该函数负责初始化CarlaCollisionPublisher,包括创建DDS域参与者、发布者、主题和数据写入器,并注册消息类型。
89 */
91 /**
92 * @brief 检查类型支持是否有效
93 * @details 如果_type为nullptr,则打印错误信息并返回false。
94 */
95 if (_impl->_type == nullptr) {
96 std::cerr << "Invalid TypeSupport" << std::endl;
97 return false;
98 }
99 /**
100 * @brief 设置域参与者QoS策略
101 * @details 使用默认的域参与者QoS策略,并设置名称。
102 */
103 efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT;
104 pqos.name(_name);
105 /**
106 * @brief 创建域参与者
107 * @details 使用DomainParticipantFactory创建域参与者,如果失败则打印错误信息并返回false。
108 */
109 auto factory = efd::DomainParticipantFactory::get_instance();
110 _impl->_participant = factory->create_participant(0, pqos);
111 if (_impl->_participant == nullptr) {
112 std::cerr << "Failed to create DomainParticipant" << std::endl;
113 return false;
114 }
115 /**
116 * @brief 注册类型支持
117 * @details 使用类型支持对象注册消息类型到域参与者。
118 */
119 _impl->_type.register_type(_impl->_participant);
120 /**
121 * @brief 设置发布者QoS策略
122 * @details 使用默认的发布者QoS策略。
123 */
124 efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT;
125 /**
126 * @brief 创建发布者
127 * @details 在域参与者中创建一个发布者,如果失败则打印错误信息并返回false。
128 */
129 _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr);
130 if (_impl->_publisher == nullptr) {
131 std::cerr << "Failed to create Publisher" << std::endl;
132 return false;
133 }
134 /**
135 * @brief 设置主题QoS策略
136 * @details 使用默认的主题QoS策略。
137 */
138 efd::TopicQos tqos = efd::TOPIC_QOS_DEFAULT;
139 /**
140 * @brief 构建主题名称
141 * @details 根据_name和_parent成员变量构建主题名称。
142 */
143 const std::string base { "rt/carla/" };
144 std::string topic_name = base;
145 if (!_parent.empty())
146 topic_name += _parent + "/";
147 topic_name += _name;
148 /**
149 * @brief 创建主题
150 * @details 在域参与者中创建一个主题,如果失败则打印错误信息并返回false。
151 */
152 _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos);
153 if (_impl->_topic == nullptr) {
154 std::cerr << "Failed to create Topic" << std::endl;
155 return false;
156 }
157 /**
158 * @brief 设置数据写入器QoS策略
159 * @details 使用默认的数据写入器QoS策略,并设置历史内存策略为预分配并允许重新分配。
160 */
161 efd::DataWriterQos wqos = efd::DATAWRITER_QOS_DEFAULT;
162 wqos.endpoint().history_memory_policy = eprosima::fastrtps::rtps::PREALLOCATED_WITH_REALLOC_MEMORY_MODE;
163 /**
164 * @brief 创建数据写入器
165 * @details 在发布者中创建一个数据写入器,并关联监听器,如果失败则打印错误信息并返回false。
166 */
167 efd::DataWriterListener* listener = (efd::DataWriterListener*)_impl->_listener._impl.get();
168 _impl->_datawriter = _impl->_publisher->create_datawriter(_impl->_topic, wqos, listener);
169 if (_impl->_datawriter == nullptr) {
170 std::cerr << "Failed to create DataWriter" << std::endl;
171 return false;
172 }
173 /**
174 * @brief 设置帧ID
175 * @details 将_frame_id设置为_name的值。
176 */
178 /**
179 * @brief 初始化成功
180 * @details 初始化所有DDS组件成功后返回true。
181 */
182 return true;
183 }
184 /**
185 * @brief 发布碰撞数据
186 *
187 * 此函数尝试通过Fast-RTPS发布碰撞事件数据。
188 * 根据返回码(ReturnCode_t)判断发布是否成功,并输出相应的错误信息。
189 *
190 * @return bool 如果发布成功返回true,否则返回false。
191 */
193 /// @brief 用于存储Fast-RTPS实例句柄的变量
194 eprosima::fastrtps::rtps::InstanceHandle_t instance_handle;
195 /// @brief 调用DataWriter的write方法尝试发布数据,并获取返回码
196 eprosima::fastrtps::types::ReturnCode_t rcode = _impl->_datawriter->write(&_impl->_event, instance_handle);
197 /// @brief 如果返回码为RETCODE_OK,表示发布成功
198 if (rcode == erc::ReturnCodeValue::RETCODE_OK) {
199 return true;
200 }
201 /// @brief 处理各种可能的错误返回码,并输出相应的错误信息
202 /// @note 以下分支处理不同的错误情况
203 if (rcode == erc::ReturnCodeValue::RETCODE_ERROR) {
204 std::cerr << "RETCODE_ERROR" << std::endl;
205 return false;
206 }
207 if (rcode == erc::ReturnCodeValue::RETCODE_UNSUPPORTED) {
208 std::cerr << "RETCODE_UNSUPPORTED" << std::endl;
209 return false;
210 }
211 if (rcode == erc::ReturnCodeValue::RETCODE_BAD_PARAMETER) {
212 std::cerr << "RETCODE_BAD_PARAMETER" << std::endl;
213 return false;
214 }
215 if (rcode == erc::ReturnCodeValue::RETCODE_PRECONDITION_NOT_MET) {
216 std::cerr << "RETCODE_PRECONDITION_NOT_MET" << std::endl;
217 return false;
218 }
219 if (rcode == erc::ReturnCodeValue::RETCODE_OUT_OF_RESOURCES) {
220 std::cerr << "RETCODE_OUT_OF_RESOURCES" << std::endl;
221 return false;
222 }
223 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ENABLED) {
224 std::cerr << "RETCODE_NOT_ENABLED" << std::endl;
225 return false;
226 }
227 if (rcode == erc::ReturnCodeValue::RETCODE_IMMUTABLE_POLICY) {
228 std::cerr << "RETCODE_IMMUTABLE_POLICY" << std::endl;
229 return false;
230 }
231 if (rcode == erc::ReturnCodeValue::RETCODE_INCONSISTENT_POLICY) {
232 std::cerr << "RETCODE_INCONSISTENT_POLICY" << std::endl;
233 return false;
234 }
235 if (rcode == erc::ReturnCodeValue::RETCODE_ALREADY_DELETED) {
236 std::cerr << "RETCODE_ALREADY_DELETED" << std::endl;
237 return false;
238 }
239 if (rcode == erc::ReturnCodeValue::RETCODE_TIMEOUT) {
240 std::cerr << "RETCODE_TIMEOUT" << std::endl;
241 return false;
242 }
243 if (rcode == erc::ReturnCodeValue::RETCODE_NO_DATA) {
244 std::cerr << "RETCODE_NO_DATA" << std::endl;
245 return false;
246 }
247 if (rcode == erc::ReturnCodeValue::RETCODE_ILLEGAL_OPERATION) {
248 std::cerr << "RETCODE_ILLEGAL_OPERATION" << std::endl;
249 return false;
250 }
251 if (rcode == erc::ReturnCodeValue::RETCODE_NOT_ALLOWED_BY_SECURITY) {
252 std::cerr << "RETCODE_NOT_ALLOWED_BY_SECURITY" << std::endl;
253 return false;
254 }
255 /// @brief 如果返回码未知,则输出"UNKNOWN"错误信息
256 std::cerr << "UNKNOWN" << std::endl;
257 return false;
258 }
259 /**
260 * @brief 设置碰撞数据,使用单独的x, y, z坐标
261 *
262 * 该函数将时间戳(秒和纳秒)、actor_id以及碰撞的x, y, z坐标作为参数,
263 * 并将这些数据封装成向量后调用重载的SetData函数。
264 *
265 * @param seconds 时间戳的秒部分
266 * @param nanoseconds 时间戳的纳秒部分
267 * @param actor_id 发生碰撞的actor的ID
268 * @param x 碰撞点的x坐标
269 * @param y 碰撞点的y坐标
270 * @param z 碰撞点的z坐标
271 */
272void CarlaCollisionPublisher::SetData(int32_t seconds, uint32_t nanoseconds, uint32_t actor_id, float x, float y, float z) {
273 std::vector<float> vector_data ;
274 SetData(seconds, nanoseconds, actor_id, {x, y, z});
275 }
276/**
277 * @brief 设置碰撞数据,使用向量数据
278 *
279 * 该函数将时间戳(秒和纳秒)、actor_id以及包含碰撞数据的向量作为参数,
280 * 并使用这些数据填充碰撞事件的消息结构。
281 *
282 * @param seconds 时间戳的秒部分
283 * @param nanoseconds 时间戳的纳秒部分
284 * @param actor_id 发生碰撞的actor的ID
285 * @param data 包含碰撞点x, y, z坐标的向量
286 */
287 void CarlaCollisionPublisher::SetData(int32_t seconds, uint32_t nanoseconds, uint32_t actor_id, std::vector<float>&& data) {
289 time.sec(seconds);
290 time.nanosec(nanoseconds);
291
292 std_msgs::msg::Header header;
293 header.stamp(std::move(time));
294 header.frame_id(_frame_id);
295
297 impulse.x(data[0]);
298 impulse.y(data[1]);
299 impulse.z(data[2]);
300 _impl->_event.header(std::move(header));
301 _impl->_event.other_actor_id(actor_id);
302 _impl->_event.normal_impulse(impulse);
303 }
304 /**
305 * @brief CarlaCollisionPublisher类的构造函数
306 *
307 * 初始化CarlaCollisionPublisher对象,包括设置ROS名称、父节点以及内部实现对象。
308 *
309 * @param ros_name ROS节点名称
310 * @param parent 父节点名称
311 */
312 CarlaCollisionPublisher::CarlaCollisionPublisher(const char* ros_name, const char* parent) :
313 _impl(std::make_shared<CarlaCollisionPublisherImpl>()) {
314 _name = ros_name;
315 _parent = parent;
316 }
317 /**
318 * @brief CarlaCollisionPublisher类的析构函数
319 *
320 * 清理资源,包括删除数据写入器、发布者、主题和参与者。
321 */
323 if (!_impl)
324 return;
325
326 if (_impl->_datawriter)
327 _impl->_publisher->delete_datawriter(_impl->_datawriter);
328
329 if (_impl->_publisher)
330 _impl->_participant->delete_publisher(_impl->_publisher);
331
332 if (_impl->_topic)
333 _impl->_participant->delete_topic(_impl->_topic);
334
335 if (_impl->_participant)
336 efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant);
337 }
338 /**
339 * @brief CarlaCollisionPublisher类的拷贝构造函数
340 *
341 * 创建并初始化一个新的CarlaCollisionPublisher对象,作为另一个CarlaCollisionPublisher对象的拷贝。
342 *
343 * @param other 要拷贝的CarlaCollisionPublisher对象
344 */
346 _frame_id = other._frame_id;
347 _name = other._name;
348 _parent = other._parent;
349 _impl = other._impl;
350 }
351 /**
352 * @brief 赋值运算符重载
353 *
354 * 将当前对象设置为另一个CarlaCollisionPublisher对象的拷贝。
355 *
356 * @param other 要拷贝的CarlaCollisionPublisher对象
357 * @return 引用当前对象
358 */
360 _frame_id = other._frame_id;
361 _name = other._name;
362 _parent = other._parent;
363 _impl = other._impl;
364
365 return *this;
366 }
367 /**
368 * @brief CarlaCollisionPublisher类的移动构造函数
369 *
370 * 创建并初始化一个新的CarlaCollisionPublisher对象,作为另一个CarlaCollisionPublisher对象的移动。
371 *
372 * @param other 要移动的CarlaCollisionPublisher对象
373 */
375 _frame_id = std::move(other._frame_id);
376 _name = std::move(other._name);
377 _parent = std::move(other._parent);
378 _impl = std::move(other._impl);
379 }
380 /**
381 * @brief 移动赋值运算符重载
382 *
383 * 将当前对象设置为另一个CarlaCollisionPublisher对象的移动。
384 *
385 * @param other 要移动的CarlaCollisionPublisher对象
386 * @return 引用当前对象
387 */
389 _frame_id = std::move(other._frame_id);
390 _name = std::move(other._name);
391 _parent = std::move(other._parent);
392 _impl = std::move(other._impl);
393
394 return *this;
395 }
396}
397}
此类表示用户在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
用于发布CARLA碰撞事件的ROS 2发布者类。
std::shared_ptr< CarlaCollisionPublisherImpl > _impl
指向内部实现结构体的智能指针。
bool Publish()
发布碰撞事件信息。
void SetData(int32_t seconds, uint32_t nanoseconds, uint32_t actor_id, float x, float y, float z)
设置要发布的碰撞事件数据。
CarlaCollisionPublisher(const char *ros_name="", const char *parent="")
构造函数,初始化CarlaCollisionPublisher。
CarlaCollisionPublisher & operator=(const CarlaCollisionPublisher &)
赋值运算符。
~CarlaCollisionPublisher()
析构函数,清理资源并释放内部实现。
const std::string & parent() const
此类代表了用户在 IDL 文件中定义的 CarlaCollisionEvent 类型的主题数据类型(TopicDataType)。
此类表示用户在 IDL 文件中定义的 Vector3 结构。 <>
Definition Vector3.h:72
eProsima_user_DllExport void x(double _x)
设置成员 x 的值
Definition Vector3.cpp:150
eProsima_user_DllExport void z(double _z)
设置成员 z 的值
Definition Vector3.cpp:189
eProsima_user_DllExport void y(double _y)
设置成员 y 的值
Definition Vector3.cpp:170
eprosima::fastrtps::types::ReturnCode_t erc
@using erc
CARLA模拟器的主命名空间。
Definition Carla.cpp:139
CarlaCollisionPublisher的内部实现结构体
carla_msgs::msg::CarlaCollisionEvent _event
CARLA碰撞事件消息
efd::DataWriter * _datawriter
DDS数据写入器指针
efd::Publisher * _publisher
DDS发布者指针
efd::DomainParticipant * _participant
DDS域参与者指针