|
27 | 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
28 | 28 | // POSSIBILITY OF SUCH DAMAGE.
|
29 | 29 |
|
30 |
| - |
31 | 30 | #ifndef RVIZ_DEFAULT_PLUGINS__DISPLAYS__POINTCLOUD__POINT_CLOUD_TRANSPORT_DISPLAY_HPP_
|
32 | 31 | #define RVIZ_DEFAULT_PLUGINS__DISPLAYS__POINTCLOUD__POINT_CLOUD_TRANSPORT_DISPLAY_HPP_
|
33 | 32 |
|
|
39 | 38 | #include "get_transport_from_topic.hpp"
|
40 | 39 | #include "point_cloud_transport/point_cloud_transport.hpp"
|
41 | 40 | #include "point_cloud_transport/subscriber_filter.hpp"
|
42 |
| -#include "rviz_common/ros_topic_display.hpp" |
| 41 | +#include "rviz_common/message_filter_display.hpp" |
43 | 42 |
|
44 | 43 | namespace rviz_default_plugins
|
45 | 44 | {
|
46 | 45 | namespace displays
|
47 | 46 | {
|
48 | 47 |
|
49 | 48 | template<class MessageType>
|
50 |
| -class PointCloud2TransportDisplay : public rviz_common::_RosTopicDisplay |
| 49 | +class PointCloud2TransportDisplay : public rviz_common::MessageFilterDisplay<MessageType> |
51 | 50 | {
|
52 |
| -// No Q_OBJECT macro here, moc does not support Q_OBJECT in a templated class. |
| 51 | + // No Q_OBJECT macro here, moc does not support Q_OBJECT in a templated class. |
53 | 52 |
|
54 | 53 | public:
|
55 |
| -/// Convenience typedef so subclasses don't have to use |
56 |
| -/// the long templated class name to refer to their super class. |
| 54 | + /// Convenience typedef so subclasses don't have to use |
| 55 | + /// the long templated class name to refer to their super class. |
57 | 56 | typedef PointCloud2TransportDisplay<MessageType> PC2RDClass;
|
58 | 57 |
|
59 |
| - PointCloud2TransportDisplay() |
60 |
| - : messages_received_(0) |
61 |
| - { |
62 |
| - QString message_type = QString::fromStdString(rosidl_generator_traits::name<MessageType>()); |
63 |
| - topic_property_->setMessageType(message_type); |
64 |
| - topic_property_->setDescription(message_type + " topic to subscribe to."); |
65 |
| - } |
66 |
| - |
67 |
| -/** |
68 |
| -* When overriding this method, the onInitialize() method of this superclass has to be called. |
69 |
| -* Otherwise, the ros node will not be initialized. |
70 |
| -*/ |
71 |
| - void onInitialize() override |
72 |
| - { |
73 |
| - _RosTopicDisplay::onInitialize(); |
74 |
| - } |
75 |
| - |
76 |
| - ~PointCloud2TransportDisplay() override |
77 |
| - { |
78 |
| - unsubscribe(); |
79 |
| - } |
80 |
| - |
81 |
| - void reset() override |
82 |
| - { |
83 |
| - Display::reset(); |
84 |
| - messages_received_ = 0; |
85 |
| - } |
86 |
| - |
87 |
| - void setTopic(const QString & topic, const QString & datatype) override |
88 |
| - { |
89 |
| - (void) datatype; |
90 |
| - topic_property_->setString(topic); |
91 |
| - } |
92 |
| - |
93 | 58 | protected:
|
94 |
| - void updateTopic() override |
| 59 | + void subscribe() override |
95 | 60 | {
|
96 |
| - resetSubscription(); |
97 |
| - } |
98 |
| - |
99 |
| - virtual void subscribe() |
100 |
| - { |
101 |
| - if (!isEnabled()) { |
| 61 | + if (!this->isEnabled()) { |
102 | 62 | return;
|
103 | 63 | }
|
104 | 64 |
|
105 |
| - if (topic_property_->isEmpty()) { |
106 |
| - setStatus( |
107 |
| - rviz_common::properties::StatusProperty::Error, "Topic", |
108 |
| - QString("Error subscribing: Empty topic name")); |
| 65 | + if (this->topic_property_->isEmpty()) { |
| 66 | + this->setStatus(rviz_common::properties::StatusProperty::Error, "Topic", |
| 67 | + QString("Error subscribing: Empty topic name")); |
109 | 68 | return;
|
110 | 69 | }
|
111 | 70 |
|
112 | 71 | try {
|
113 |
| - subscription_ = std::make_shared<point_cloud_transport::SubscriberFilter>(); |
114 |
| - subscription_->subscribe( |
115 |
| - *rviz_ros_node_.lock()->get_raw_node(), |
116 |
| - getPointCloud2BaseTopicFromTopic(topic_property_->getTopicStd()), |
117 |
| - getPointCloud2TransportFromTopic(topic_property_->getTopicStd()), |
118 |
| - qos_profile); |
119 |
| - subscription_start_time_ = rviz_ros_node_.lock()->get_raw_node()->now(); |
120 |
| - subscription_callback_ = subscription_->registerCallback( |
121 |
| - std::bind( |
122 |
| - &PointCloud2TransportDisplay<MessageType>::incomingMessage, this, std::placeholders::_1)); |
123 |
| - setStatus(rviz_common::properties::StatusProperty::Ok, "Topic", "OK"); |
| 72 | + rclcpp::Node::SharedPtr node = this->rviz_ros_node_.lock()->get_raw_node(); |
| 73 | + subscriber_filter_ = std::make_shared<point_cloud_transport::SubscriberFilter>(); |
| 74 | + subscriber_filter_->subscribe( |
| 75 | + rclcpp::node_interfaces::NodeInterfaces< |
| 76 | + rclcpp::node_interfaces::NodeBaseInterface, |
| 77 | + rclcpp::node_interfaces::NodeParametersInterface, |
| 78 | + rclcpp::node_interfaces::NodeTopicsInterface, |
| 79 | + rclcpp::node_interfaces::NodeLoggingInterface>(*node), |
| 80 | + getPointCloud2BaseTopicFromTopic(this->topic_property_->getTopicStd()), |
| 81 | + getPointCloud2TransportFromTopic(this->topic_property_->getTopicStd()), |
| 82 | + this->qos_profile); |
| 83 | + this->subscription_start_time_ = node->now(); |
| 84 | + this->tf_filter_ = |
| 85 | + std::make_shared<tf2_ros::MessageFilter<MessageType, |
| 86 | + rviz_common::transformation::FrameTransformer>>( |
| 87 | + *this->context_->getFrameManager()->getTransformer(), |
| 88 | + this->fixed_frame_.toStdString(), |
| 89 | + static_cast<uint32_t>(this->message_queue_property_->getInt()), node); |
| 90 | + this->tf_filter_->connectInput(*subscriber_filter_); |
| 91 | + this->tf_filter_->registerCallback( |
| 92 | + std::bind(&PointCloud2TransportDisplay<MessageType>::messageTaken, this, |
| 93 | + std::placeholders::_1)); |
| 94 | + this->setStatus(rviz_common::properties::StatusProperty::Ok, "Topic", "OK"); |
124 | 95 | } catch (rclcpp::exceptions::InvalidTopicNameError & e) {
|
125 |
| - setStatus( |
126 |
| - rviz_common::properties::StatusProperty::Error, "Topic", |
127 |
| - QString("Error subscribing: ") + e.what()); |
| 96 | + this->setStatus(rviz_common::properties::StatusProperty::Error, "Topic", |
| 97 | + QString("Error subscribing: ") + e.what()); |
128 | 98 | }
|
129 | 99 | }
|
130 | 100 |
|
131 |
| - void transformerChangedCallback() override |
132 |
| - { |
133 |
| - resetSubscription(); |
134 |
| - } |
135 |
| - |
136 |
| - void resetSubscription() |
137 |
| - { |
138 |
| - unsubscribe(); |
139 |
| - reset(); |
140 |
| - subscribe(); |
141 |
| - context_->queueRender(); |
142 |
| - } |
143 |
| - |
144 | 101 | virtual void unsubscribe()
|
145 | 102 | {
|
146 |
| - subscription_.reset(); |
147 |
| - } |
148 |
| - |
149 |
| - void onEnable() override |
150 |
| - { |
151 |
| - subscribe(); |
| 103 | + rviz_common::MessageFilterDisplay<MessageType>::unsubscribe(); |
| 104 | + subscriber_filter_.reset(); |
152 | 105 | }
|
153 | 106 |
|
154 |
| - void onDisable() override |
155 |
| - { |
156 |
| - unsubscribe(); |
157 |
| - reset(); |
158 |
| - } |
159 |
| - |
160 |
| -/// Incoming message callback. |
161 |
| -/** |
162 |
| -* Checks if the message pointer |
163 |
| -* is valid, increments messages_received_, then calls |
164 |
| -* processMessage(). |
165 |
| -*/ |
166 |
| - void incomingMessage(const typename MessageType::ConstSharedPtr msg) |
167 |
| - { |
168 |
| - if (!msg) { |
169 |
| - return; |
170 |
| - } |
171 |
| - |
172 |
| - ++messages_received_; |
173 |
| - QString topic_str = QString::number(messages_received_) + " messages received"; |
174 |
| - rviz_common::properties::StatusProperty::Level topic_status_level = |
175 |
| - rviz_common::properties::StatusProperty::Ok; |
176 |
| - // Append topic subscription frequency if we can lock rviz_ros_node_. |
177 |
| - std::shared_ptr<rviz_common::ros_integration::RosNodeAbstractionIface> node_interface = |
178 |
| - rviz_ros_node_.lock(); |
179 |
| - if (node_interface != nullptr) { |
180 |
| - try { |
181 |
| - const double duration = |
182 |
| - (node_interface->get_raw_node()->now() - subscription_start_time_).seconds(); |
183 |
| - const double subscription_frequency = |
184 |
| - static_cast<double>(messages_received_) / duration; |
185 |
| - topic_str += " at " + QString::number(subscription_frequency, 'f', 1) + " hz."; |
186 |
| - } catch (const std::runtime_error & e) { |
187 |
| - if (std::string(e.what()).find("can't subtract times with different time sources") != |
188 |
| - std::string::npos) |
189 |
| - { |
190 |
| - topic_status_level = rviz_common::properties::StatusProperty::Warn; |
191 |
| - topic_str += ". "; |
192 |
| - topic_str += e.what(); |
193 |
| - } else { |
194 |
| - throw; |
195 |
| - } |
196 |
| - } |
197 |
| - } |
198 |
| - setStatus( |
199 |
| - topic_status_level, |
200 |
| - "Topic", |
201 |
| - topic_str); |
202 |
| - |
203 |
| - processMessage(msg); |
204 |
| - } |
205 |
| - |
206 |
| - |
207 |
| -/// Implement this to process the contents of a message. |
208 |
| -/** |
209 |
| -* This is called by incomingMessage(). |
210 |
| -*/ |
211 |
| - virtual void processMessage(typename MessageType::ConstSharedPtr msg) = 0; |
212 |
| - |
213 |
| - uint32_t messages_received_; |
214 |
| - rclcpp::Time subscription_start_time_; |
215 |
| - |
216 |
| - std::shared_ptr<point_cloud_transport::SubscriberFilter> subscription_; |
217 |
| - message_filters::Connection subscription_callback_; |
| 107 | + std::shared_ptr<point_cloud_transport::SubscriberFilter> subscriber_filter_; |
218 | 108 | };
|
219 | 109 |
|
220 | 110 | } // end namespace displays
|
221 | 111 | } // end namespace rviz_default_plugins
|
222 | 112 |
|
223 |
| - |
224 | 113 | #endif // RVIZ_DEFAULT_PLUGINS__DISPLAYS__POINTCLOUD__POINT_CLOUD_TRANSPORT_DISPLAY_HPP_
|
0 commit comments