BridgePublisher.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <deque>
4 #include <thread>
5 #include <type_traits>
6 #include <typeinfo>
7 
8 #include "depthai/depthai.hpp"
9 
10 // #include <depthai_ros_msgs/DetectionDaiArray.h>
11 // #include <vision_msgs/Detection2DArray.h>
12 
13 #ifdef IS_ROS2
14  #include <camera_info_manager/camera_info_manager.hpp>
15  #include <image_transport/image_transport.hpp>
16 
17  #include "rclcpp/rclcpp.hpp"
18  #include "sensor_msgs/msg/camera_info.hpp"
19  #include "sensor_msgs/msg/image.hpp"
20  #include "std_msgs/msg/header.hpp"
21 #else
24  #include <ros/console.h>
25  #include <ros/ros.h>
26 
27  #include <boost/make_shared.hpp>
28  #include <boost/shared_ptr.hpp>
29 
30  #include "sensor_msgs/Image.h"
31 #endif
32 
33 namespace dai {
34 
35 namespace ros {
36 
37 #ifdef IS_ROS2
38 namespace StdMsgs = std_msgs::msg;
39 namespace ImageMsgs = sensor_msgs::msg;
40 using ImagePtr = ImageMsgs::Image::SharedPtr;
41 namespace rosOrigin = ::rclcpp;
42 #else
43 namespace StdMsgs = std_msgs;
44 namespace ImageMsgs = sensor_msgs;
46 namespace rosOrigin = ::ros;
47 #endif
48 
49 template <class RosMsg, class SimMsg>
51  public:
52  using ConvertFunc = std::function<void(std::shared_ptr<SimMsg>, std::deque<RosMsg>&)>;
53 
54 #ifdef IS_ROS2
55  using CustomPublisher = typename std::conditional<std::is_same<RosMsg, ImageMsgs::Image>::value,
56  std::shared_ptr<image_transport::Publisher>,
57  typename rclcpp::Publisher<RosMsg>::SharedPtr>::type;
58 
59  BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
60  std::shared_ptr<rclcpp::Node> node,
61  std::string rosTopic,
62  ConvertFunc converter,
63  rclcpp::QoS qosSetting = rclcpp::QoS(rclcpp::KeepLast(1)).transient_local().reliable());
64 
65  BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
66  std::shared_ptr<rclcpp::Node> node,
67  std::string rosTopic,
68  ConvertFunc converter,
69  size_t qosHistoryDepth,
70  std::string cameraParamUri = "",
71  std::string cameraName = "");
72 
73  BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
74  std::shared_ptr<rclcpp::Node> node,
75  std::string rosTopic,
76  ConvertFunc converter,
77  size_t qosHistoryDepth,
78  ImageMsgs::CameraInfo cameraInfoData,
79  std::string cameraName);
80 
84  std::shared_ptr<image_transport::Publisher> advertise(int queueSize, std::true_type);
85 
89  typename rclcpp::Publisher<RosMsg>::SharedPtr advertise(int queueSize, std::false_type);
90 #else
91  using CustomPublisher = typename std::
92  conditional<std::is_same<RosMsg, ImageMsgs::Image>::value, std::shared_ptr<image_transport::Publisher>, std::shared_ptr<rosOrigin::Publisher> >::type;
93 
94  BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
96  std::string rosTopic,
97  ConvertFunc converter,
98  int queueSize,
99  std::string cameraParamUri = "",
100  std::string cameraName = "");
101 
102  BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
104  std::string rosTopic,
105  ConvertFunc converter,
106  int queueSize,
107  ImageMsgs::CameraInfo cameraInfoData,
108  std::string cameraName);
109 
113  std::shared_ptr<image_transport::Publisher> advertise(int queueSize, std::true_type);
114 
118  std::shared_ptr<rosOrigin::Publisher> advertise(int queueSize, std::false_type);
119 
120 #endif
121 
122  BridgePublisher(const BridgePublisher& other);
123 
124  void addPublisherCallback();
125 
126  void publishHelper(std::shared_ptr<SimMsg> inData);
127 
128  void startPublisherThread();
129 
131 
132  private:
137  void daiCallback(std::string name, std::shared_ptr<ADatatype> data);
138 
139  static const std::string LOG_TAG;
140  std::shared_ptr<dai::DataOutputQueue> _daiMessageQueue;
142 
143 #ifdef IS_ROS2
144  std::shared_ptr<rclcpp::Node> _node;
145  rclcpp::Publisher<sensor_msgs::msg::CameraInfo>::SharedPtr _cameraInfoPublisher;
146 #else
148  std::shared_ptr<rosOrigin::Publisher> _cameraInfoPublisher;
149 #endif
150 
152  ImageMsgs::CameraInfo _cameraInfoData;
154 
155  std::thread _readingThread;
157  std::unique_ptr<camera_info_manager::CameraInfoManager> _camInfoManager;
158  bool _isCallbackAdded = false;
159  bool _isImageMessage = false; // used to enable camera info manager
160 };
161 
162 template <class RosMsg, class SimMsg>
163 const std::string BridgePublisher<RosMsg, SimMsg>::LOG_TAG = "BridgePublisher";
164 
165 #ifdef IS_ROS2
166 template <class RosMsg, class SimMsg>
167 BridgePublisher<RosMsg, SimMsg>::BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
168  std::shared_ptr<rclcpp::Node> node,
169  std::string rosTopic,
170  ConvertFunc converter,
171  rclcpp::QoS qosSetting)
172  : _daiMessageQueue(daiMessageQueue), _node(node), _converter(converter), _it(node), _rosTopic(rosTopic) {
173  _rosPublisher = _node->create_publisher<RosMsg>(_rosTopic, qosSetting);
174 }
175 
176 template <class RosMsg, class SimMsg>
177 BridgePublisher<RosMsg, SimMsg>::BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
178  std::shared_ptr<rclcpp::Node> node,
179  std::string rosTopic,
180  ConvertFunc converter,
181  size_t qosHistoryDepth,
182  std::string cameraParamUri,
183  std::string cameraName)
184  : _daiMessageQueue(daiMessageQueue),
185  _node(node),
186  _converter(converter),
187  _it(node),
188  _rosTopic(rosTopic),
189  _cameraParamUri(cameraParamUri),
190  _cameraName(cameraName) {
191  _rosPublisher = advertise(qosHistoryDepth, std::is_same<RosMsg, ImageMsgs::Image>{});
192 }
193 
194 template <class RosMsg, class SimMsg>
195 BridgePublisher<RosMsg, SimMsg>::BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
196  std::shared_ptr<rclcpp::Node> node,
197  std::string rosTopic,
198  ConvertFunc converter,
199  size_t qosHistoryDepth,
200  ImageMsgs::CameraInfo cameraInfoData,
201  std::string cameraName)
202  : _daiMessageQueue(daiMessageQueue),
203  _node(node),
204  _converter(converter),
205  _it(node),
206  _rosTopic(rosTopic),
207  _cameraInfoData(cameraInfoData),
208  _cameraName(cameraName) {
209  _rosPublisher = advertise(qosHistoryDepth, std::is_same<RosMsg, ImageMsgs::Image>{});
210 }
211 
212 template <class RosMsg, class SimMsg>
213 typename rclcpp::Publisher<RosMsg>::SharedPtr BridgePublisher<RosMsg, SimMsg>::advertise(int queueSize, std::false_type) {
214  return _node->create_publisher<RosMsg>(_rosTopic, queueSize);
215 }
216 
217 template <class RosMsg, class SimMsg>
218 std::shared_ptr<image_transport::Publisher> BridgePublisher<RosMsg, SimMsg>::advertise(int queueSize, std::true_type) {
219  if(!_cameraName.empty()) {
220  _isImageMessage = true;
221  _camInfoManager = std::make_unique<camera_info_manager::CameraInfoManager>(_node.get(), _cameraName, _cameraParamUri);
222  if(_cameraParamUri.empty()) {
223  _camInfoManager->setCameraInfo(_cameraInfoData);
224  }
225  // _rosPublisher = _it.advertise(rosTopic, queueSize);
226  _cameraInfoPublisher = _node->create_publisher<ImageMsgs::CameraInfo>(_cameraName + "/camera_info", queueSize);
227  }
228  return std::make_shared<image_transport::Publisher>(_it.advertise(_rosTopic, queueSize));
229 }
230 
231 #else
232 template <class RosMsg, class SimMsg>
233 BridgePublisher<RosMsg, SimMsg>::BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
235  std::string rosTopic,
236  ConvertFunc converter,
237  int queueSize,
238  std::string cameraParamUri,
239  std::string cameraName)
240  : _daiMessageQueue(daiMessageQueue),
241  _converter(converter),
242  _nh(nh),
243  _it(_nh),
244  _rosTopic(rosTopic),
245  _cameraParamUri(cameraParamUri),
246  _cameraName(cameraName) {
247  // ROS_DEBUG_STREAM_NAMED(LOG_TAG, "Publisher Type : " << typeid(CustomPublisher).name());
248  _rosPublisher = advertise(queueSize, std::is_same<RosMsg, ImageMsgs::Image>{});
249 }
250 
251 template <class RosMsg, class SimMsg>
252 BridgePublisher<RosMsg, SimMsg>::BridgePublisher(std::shared_ptr<dai::DataOutputQueue> daiMessageQueue,
254  std::string rosTopic,
255  ConvertFunc converter,
256  int queueSize,
257  ImageMsgs::CameraInfo cameraInfoData,
258  std::string cameraName)
259  : _daiMessageQueue(daiMessageQueue),
260  _nh(nh),
261  _converter(converter),
262  _it(_nh),
263  _cameraInfoData(cameraInfoData),
264  _rosTopic(rosTopic),
265  _cameraName(cameraName) {
266  // ROS_DEBUG_STREAM_NAMED(LOG_TAG, "Publisher Type : " << typeid(CustomPublisher).name());
267  _rosPublisher = advertise(queueSize, std::is_same<RosMsg, ImageMsgs::Image>{});
268 }
269 
270 template <class RosMsg, class SimMsg>
271 std::shared_ptr<rosOrigin::Publisher> BridgePublisher<RosMsg, SimMsg>::advertise(int queueSize, std::false_type) {
272  return std::make_shared<rosOrigin::Publisher>(_nh.advertise<RosMsg>(_rosTopic, queueSize));
273 }
274 
275 template <class RosMsg, class SimMsg>
276 std::shared_ptr<image_transport::Publisher> BridgePublisher<RosMsg, SimMsg>::advertise(int queueSize, std::true_type) {
277  if(!_cameraName.empty()) {
278  _isImageMessage = true;
279  _camInfoManager = std::make_unique<camera_info_manager::CameraInfoManager>(rosOrigin::NodeHandle{_nh, _cameraName}, _cameraName, _cameraParamUri);
280  if(_cameraParamUri.empty()) {
281  _camInfoManager->setCameraInfo(_cameraInfoData);
282  }
283  _cameraInfoPublisher = std::make_shared<rosOrigin::Publisher>(_nh.advertise<ImageMsgs::CameraInfo>(_cameraName + "/camera_info", queueSize));
284  }
285  return std::make_shared<image_transport::Publisher>(_it.advertise(_rosTopic, queueSize));
286 }
287 
288 template <class RosMsg, class SimMsg>
291  _nh = other._nh;
292  _converter = other._converter;
293  _rosTopic = other._rosTopic;
294  _it = other._it;
296 
297  if(other._isImageMessage) {
298  _isImageMessage = true;
299  _camInfoManager = std::make_unique<camera_info_manager::CameraInfoManager>(std::move(other._camInfoManager));
301  }
302 }
303 #endif
304 
305 template <class RosMsg, class SimMsg>
306 void BridgePublisher<RosMsg, SimMsg>::daiCallback(std::string name, std::shared_ptr<ADatatype> data) {
307  // std::cout << "In callback " << name << std::endl;
308  auto daiDataPtr = std::dynamic_pointer_cast<SimMsg>(data);
309  publishHelper(daiDataPtr);
310 }
311 
312 template <class RosMsg, class SimMsg>
314  if(_isCallbackAdded) {
315  std::runtime_error(
316  "addPublisherCallback() function adds a callback to the"
317  "depthai which handles the publishing so no need to start"
318  "the thread using startPublisherThread() ");
319  }
320 
321  _readingThread = std::thread([&]() {
322  int messageCounter = 0;
323  while(rosOrigin::ok()) {
324  // auto daiDataPtr = _daiMessageQueue->get<SimMsg>();
325  auto daiDataPtr = _daiMessageQueue->tryGet<SimMsg>();
326  if(daiDataPtr == nullptr) {
327  messageCounter++;
328  if(messageCounter > 2000000) {
329  // ROS_WARN_STREAM_NAMED(LOG_TAG,
330  // "Missing " << messageCounter << " number of Incoming message from Depthai Queue " << _daiMessageQueue->getName());
331  messageCounter = 0;
332  }
333  continue;
334  }
335 
336  if(messageCounter != 0) {
337  messageCounter = 0;
338  }
339  publishHelper(daiDataPtr);
340  }
341  });
342 }
343 
344 template <class RosMsg, class SimMsg>
346  _daiMessageQueue->addCallback(std::bind(&BridgePublisher<RosMsg, SimMsg>::daiCallback, this, std::placeholders::_1, std::placeholders::_2));
347  _isCallbackAdded = true;
348 }
349 
350 template <class RosMsg, class SimMsg>
351 void BridgePublisher<RosMsg, SimMsg>::publishHelper(std::shared_ptr<SimMsg> inDataPtr) {
352  std::deque<RosMsg> opMsgs;
353 
354  int infoSubCount = 0, mainSubCount = 0;
355 #ifndef IS_ROS2
356  if(_isImageMessage) {
357  infoSubCount = _cameraInfoPublisher->getNumSubscribers();
358  }
359  mainSubCount = _rosPublisher->getNumSubscribers();
360 #else
361  if(_isImageMessage) {
362  infoSubCount = _node->count_subscribers(_cameraName + "/camera_info");
363  }
364  mainSubCount = _node->count_subscribers(_rosTopic);
365 #endif
366 
367  if(mainSubCount > 0 || infoSubCount > 0) {
368  _converter(inDataPtr, opMsgs);
369 
370  while(opMsgs.size()) {
371  RosMsg currMsg = opMsgs.front();
372  if(mainSubCount > 0) {
373  _rosPublisher->publish(currMsg);
374  }
375 
376  if(infoSubCount > 0) {
377  // if (_isImageMessage){
378  // _camInfoFrameId = curr.header.frame_id
379  // }
380  auto localCameraInfo = _camInfoManager->getCameraInfo();
381 #ifndef IS_ROS2
382  localCameraInfo.header.seq = currMsg.header.seq;
383 #endif
384  localCameraInfo.header.stamp = currMsg.header.stamp;
385  localCameraInfo.header.frame_id = currMsg.header.frame_id;
386  _cameraInfoPublisher->publish(localCameraInfo);
387  }
388  opMsgs.pop_front();
389  }
390  }
391 }
392 
393 template <class RosMsg, class SimMsg>
395  if(_readingThread.joinable()) _readingThread.join();
396 }
397 
398 } // namespace ros
399 
400 namespace rosBridge = ros;
401 
402 } // namespace dai
void publishHelper(std::shared_ptr< SimMsg > inData)
std::unique_ptr< camera_info_manager::CameraInfoManager > _camInfoManager
ImageMsgs::CameraInfo _cameraInfoData
std::shared_ptr< image_transport::Publisher > advertise(int queueSize, std::true_type)
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
typename std::conditional< std::is_same< RosMsg, ImageMsgs::Image >::value, std::shared_ptr< image_transport::Publisher >, std::shared_ptr< rosOrigin::Publisher > >::type CustomPublisher
void daiCallback(std::string name, std::shared_ptr< ADatatype > data)
std::shared_ptr< rosOrigin::Publisher > _cameraInfoPublisher
ImageMsgs::ImagePtr ImagePtr
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
std::function< void(std::shared_ptr< SimMsg >, std::deque< RosMsg > &)> ConvertFunc
BridgePublisher(std::shared_ptr< dai::DataOutputQueue > daiMessageQueue, rosOrigin::NodeHandle nh, std::string rosTopic, ConvertFunc converter, int queueSize, std::string cameraParamUri="", std::string cameraName="")
rosOrigin::NodeHandle _nh
image_transport::ImageTransport _it
static const std::string LOG_TAG
std::shared_ptr< dai::DataOutputQueue > _daiMessageQueue


depthai_bridge
Author(s): Sachin Guruswamy
autogenerated on Tue May 10 2022 03:01:27