Skip to content

Commit 752fa43

Browse files
committed
property to override transport, make sure transport is installed before subscribing
1 parent 5d7eebc commit 752fa43

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

rviz_default_plugins/include/rviz_default_plugins/displays/image/image_display.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,13 @@ class RVIZ_DEFAULT_PLUGINS_PUBLIC ImageDisplay
8787
public Q_SLOTS:
8888
virtual void updateNormalizeOptions();
8989

90+
protected Q_SLOTS:
91+
void updateTopic() override;
92+
void subscribe() override;
93+
9094
protected:
9195
void onEnable() override;
9296
void onDisable() override;
93-
void subscribe() override;
9497
void unsubscribe() override;
9598

9699
void incomingMessage(const sensor_msgs::msg::Image::ConstSharedPtr & img_msg);
@@ -113,6 +116,7 @@ public Q_SLOTS:
113116

114117
std::unique_ptr<rviz_common::RenderPanel> render_panel_;
115118

119+
rviz_common::properties::EnumProperty * transport_override_property_;
116120
rviz_common::properties::BoolProperty * normalize_property_;
117121
rviz_common::properties::FloatProperty * min_property_;
118122
rviz_common::properties::FloatProperty * max_property_;

rviz_default_plugins/src/rviz_default_plugins/displays/image/image_display.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ ImageDisplay::ImageDisplay(std::unique_ptr<ROSImageTextureIface> texture)
8787
this->qos_profile_property_ =
8888
new rviz_common::properties::QosProfileProperty(this->topic_property_, rclcpp::QoS(5));
8989

90+
transport_override_property_ = new rviz_common::properties::EnumProperty(
91+
"Transport Override", "", "By default this display uses the topic name to determine the" +
92+
" image_transport type. If this is not possible, use this field to manually set the transport.",
93+
this->topic_property_, SLOT(subscribe()), this
94+
);
95+
9096
normalize_property_ = new rviz_common::properties::BoolProperty(
9197
"Normalize Range", true,
9298
"If set to true, will try to estimate the range of possible values from the received images.",
@@ -136,16 +142,16 @@ void ImageDisplay::incomingMessage(const sensor_msgs::msg::Image::ConstSharedPtr
136142
ImageTransportDisplay<sensor_msgs::msg::Image>::incomingMessage(img_msg);
137143
}
138144

139-
void ImageDisplay::subscribe()
145+
void ImageDisplay::updateTopic()
140146
{
141147
if (!isEnabled()) {
142148
return;
143149
}
150+
transport_override_property_->setStdString("");
144151

145-
// TODO(mjforan) this should really be in onInitialize but setStatus does not work there
146152
// Populate topic message types based on installed image_transport plugins
147153
image_transport::ImageTransport image_transport_(rviz_ros_node_.lock()->get_raw_node());
148-
std::vector<std::string> transports = image_transport_.getLoadableTransports();
154+
std::vector<std::string> loadable_transports = image_transport_.getLoadableTransports();
149155
std::vector<QString> message_types;
150156
// Map to message types
151157
const std::unordered_map<std::string, std::string> transport_message_types_ = {
@@ -158,10 +164,13 @@ void ImageDisplay::subscribe()
158164
std::string transports_str = "";
159165
rviz_common::properties::StatusProperty::Level transports_status_level =
160166
rviz_common::properties::StatusProperty::Ok;
161-
for (std::string & transport : transports) {
167+
// Populate topic message types and transport override options
168+
transport_override_property_->addOptionStd("");
169+
for (std::string & transport : loadable_transports) {
162170
transport = transport.substr(transport.find_last_of('/') + 1);
163171
try {
164172
message_types.push_back(QString::fromStdString(transport_message_types_.at(transport)));
173+
transport_override_property_->addOptionStd(transport);
165174
transports_str += transport + ", ";
166175
} catch (const std::out_of_range & e) {
167176
transports_status_level = rviz_common::properties::StatusProperty::Warn;
@@ -175,26 +184,51 @@ void ImageDisplay::subscribe()
175184
((rviz_common::properties::RosTopicMultiProperty *)topic_property_)
176185
->setMessageTypes(message_types);
177186

187+
rviz_default_plugins::displays::ImageTransportDisplay<sensor_msgs::msg::Image>::updateTopic();
188+
}
189+
190+
void ImageDisplay::subscribe()
191+
{
192+
if (!isEnabled()) {
193+
return;
194+
}
195+
178196
if (topic_property_->isEmpty()) {
179197
setStatus(
180198
rviz_common::properties::StatusProperty::Error, "Topic",
181199
QString("Error subscribing: Empty topic name"));
182200
return;
183201
}
184-
185202
try {
186203
rclcpp::Node::SharedPtr node = rviz_ros_node_.lock()->get_raw_node();
187204
image_transport::ImageTransport image_transport_(node);
188205
// This part differs from the parent class. ImageTransportDisplay uses an
189206
// image_transport::SubscriberFilter, which requires a different callback for each transport
190207
// type. image_transport::Subscriber only requires one callback for "raw" and the other types
191208
// are automatically converted.
209+
std::vector<std::string> transports = image_transport_.getLoadableTransports();
210+
// Strip down to basic transport names
211+
for (std::string & transport : transports) {
212+
transport = transport.substr(transport.find_last_of('/') + 1);
213+
}
214+
// Use override property for transport hint if set, otherwise deduce from topic name
215+
std::string transport_hint = transport_override_property_->getStdString();
216+
if (transport_hint.empty()) {
217+
transport_hint = getTransportFromTopic(topic_property_->getStdString());
218+
}
219+
// Check if the specified transport is in the list of loadable transports
220+
if (std::find(transports.begin(), transports.end(), transport_hint) == transports.end()) {
221+
setStatus(
222+
rviz_common::properties::StatusProperty::Error, "Topic",
223+
QString("Error subscribing: Specified image transport is not installed"));
224+
return;
225+
}
192226
subscription_ = image_transport_.subscribe(
193227
rviz_default_plugins::displays::getBaseTopicFromTopic(topic_property_->getTopicStd()),
194228
qos_profile.get_rmw_qos_profile().depth,
195229
&ImageDisplay::incomingMessage, this,
196230
new image_transport::TransportHints(
197-
node.get(), getTransportFromTopic(topic_property_->getStdString()), "image_transport"));
231+
node.get(), transport_hint, "image_transport"));
198232

199233
setStatus(rviz_common::properties::StatusProperty::Ok, "Topic", "OK");
200234
} catch (rclcpp::exceptions::InvalidTopicNameError & e) {

0 commit comments

Comments
 (0)