Skip to content

Commit e9cc51d

Browse files
committed
property to override transport, make sure transport is installed before subscribing
1 parent 03b70a4 commit e9cc51d

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
@@ -85,6 +85,12 @@ ImageDisplay::ImageDisplay(std::unique_ptr<ROSImageTextureIface> texture)
8585
this->qos_profile_property_ =
8686
new rviz_common::properties::QosProfileProperty(this->topic_property_, rclcpp::QoS(5));
8787

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

137-
void ImageDisplay::subscribe()
143+
void ImageDisplay::updateTopic()
138144
{
139145
if (!isEnabled()) {
140146
return;
141147
}
148+
transport_override_property_->setStdString("");
142149

143-
// TODO(mjforan) this should really be in onInitialize but setStatus does not work there
144150
// Populate topic message types based on installed image_transport plugins
145151
image_transport::ImageTransport image_transport_(rviz_ros_node_.lock()->get_raw_node());
146-
std::vector<std::string> transports = image_transport_.getLoadableTransports();
152+
std::vector<std::string> loadable_transports = image_transport_.getLoadableTransports();
147153
std::vector<QString> message_types;
148154
// Map to message types
149155
const std::unordered_map<std::string, std::string> transport_message_types_ = {
@@ -156,10 +162,13 @@ void ImageDisplay::subscribe()
156162
std::string transports_str = "";
157163
rviz_common::properties::StatusProperty::Level transports_status_level =
158164
rviz_common::properties::StatusProperty::Ok;
159-
for (std::string & transport : transports) {
165+
// Populate topic message types and transport override options
166+
transport_override_property_->addOptionStd("");
167+
for (std::string & transport : loadable_transports) {
160168
transport = transport.substr(transport.find_last_of('/') + 1);
161169
try {
162170
message_types.push_back(QString::fromStdString(transport_message_types_.at(transport)));
171+
transport_override_property_->addOptionStd(transport);
163172
transports_str += transport + ", ";
164173
} catch (const std::out_of_range & e) {
165174
transports_status_level = rviz_common::properties::StatusProperty::Warn;
@@ -173,26 +182,51 @@ void ImageDisplay::subscribe()
173182
((rviz_common::properties::RosTopicMultiProperty *)topic_property_)
174183
->setMessageTypes(message_types);
175184

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

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

0 commit comments

Comments
 (0)