Skip to content

Commit 9e3e88a

Browse files
rviz common ros service property (#1548)
Signed-off-by: Joshua Supratman <[email protected]> Signed-off-by: Alejandro Hernández Cordero <[email protected]> Co-authored-by: Alejandro Hernández Cordero <[email protected]> Co-authored-by: Alejandro Hernández Cordero <[email protected]>
1 parent 815ebb2 commit 9e3e88a

File tree

6 files changed

+289
-0
lines changed

6 files changed

+289
-0
lines changed

rviz_common/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ set(rviz_common_headers_to_moc
111111
include/rviz_common/properties/property_tree_with_help.hpp
112112
include/rviz_common/properties/qos_profile_property.hpp
113113
include/rviz_common/properties/ros_action_property.hpp
114+
include/rviz_common/properties/ros_service_property.hpp
114115
include/rviz_common/properties/ros_topic_property.hpp
115116
include/rviz_common/properties/status_list.hpp
116117
include/rviz_common/properties/status_property.hpp
@@ -192,6 +193,7 @@ set(rviz_common_source_files
192193
src/rviz_common/properties/property_tree_with_help.cpp
193194
src/rviz_common/properties/property.cpp
194195
src/rviz_common/properties/ros_action_property.cpp
196+
src/rviz_common/properties/ros_service_property.cpp
195197
src/rviz_common/properties/ros_topic_property.cpp
196198
src/rviz_common/properties/quaternion_property.cpp
197199
src/rviz_common/properties/qos_profile_property.cpp
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright (c) 2025, Open Source Robotics Foundation, Inc.
2+
// All rights reserved.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// * Redistributions of source code must retain the above copyright
8+
// notice, this list of conditions and the following disclaimer.
9+
//
10+
// * Redistributions in binary form must reproduce the above copyright
11+
// notice, this list of conditions and the following disclaimer in the
12+
// documentation and/or other materials provided with the distribution.
13+
//
14+
// * Neither the name of the copyright holder nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
// POSSIBILITY OF SUCH DAMAGE.
29+
#ifndef RVIZ_COMMON__PROPERTIES__ROS_SERVICE_PROPERTY_HPP_
30+
#define RVIZ_COMMON__PROPERTIES__ROS_SERVICE_PROPERTY_HPP_
31+
32+
#include <QObject>
33+
#include <QRegExp>
34+
#include <QString>
35+
36+
#include <memory>
37+
#include <string>
38+
39+
#include "rviz_common/properties/editable_enum_property.hpp"
40+
#include "rviz_common/ros_integration/ros_node_abstraction_iface.hpp"
41+
#include "rviz_common/visibility_control.hpp"
42+
43+
namespace rviz_common
44+
{
45+
namespace properties
46+
{
47+
48+
class RVIZ_COMMON_PUBLIC RosServiceProperty : public EditableEnumProperty
49+
{
50+
Q_OBJECT
51+
52+
public:
53+
explicit RosServiceProperty(
54+
const QString & name = QString(),
55+
const QString & default_value = QString(),
56+
const QString & service_type = QString(),
57+
const QString & description = QString(),
58+
Property * parent = nullptr,
59+
const char * changed_slot = nullptr,
60+
QObject * receiver = nullptr);
61+
62+
void initialize(ros_integration::RosNodeAbstractionIface::WeakPtr rviz_ros_node);
63+
64+
void setServiceType(const QString & service_type);
65+
66+
QString getServiceType() const;
67+
68+
QString getService() const;
69+
70+
std::string getServiceStd() const;
71+
72+
bool isEmpty() const;
73+
74+
protected Q_SLOTS:
75+
virtual void fillServiceList();
76+
77+
private:
78+
ros_integration::RosNodeAbstractionIface::WeakPtr rviz_ros_node_;
79+
QString service_type_;
80+
};
81+
82+
class RVIZ_COMMON_PUBLIC RosFilteredServiceProperty
83+
: public rviz_common::properties::RosServiceProperty
84+
{
85+
Q_OBJECT
86+
87+
public:
88+
RosFilteredServiceProperty(
89+
const QString & name = QString(),
90+
const QString & default_value = QString(),
91+
const QString & service_type = QString(),
92+
const QString & description = QString(),
93+
const QRegExp & filter = QRegExp(),
94+
Property * parent = 0,
95+
const char * changed_slot = 0,
96+
QObject * receiver = 0);
97+
98+
void enableFilter(bool enabled);
99+
100+
QRegExp filter() const;
101+
102+
protected Q_SLOTS:
103+
void fillServiceList() override;
104+
105+
private:
106+
QRegExp filter_;
107+
bool filter_enabled_;
108+
};
109+
110+
} // end namespace properties
111+
} // end namespace rviz_common
112+
113+
#endif // RVIZ_COMMON__PROPERTIES__ROS_SERVICE_PROPERTY_HPP_

rviz_common/include/rviz_common/ros_integration/ros_node_abstraction.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@ class RosNodeAbstraction : public RosNodeAbstractionIface
8585
std::map<std::string, std::vector<std::string>>
8686
get_topic_names_and_types() const override;
8787

88+
/// Return a map with service names mapped to a list of types for that service.
89+
/**
90+
* The node name is what was given when initializing this API.
91+
*
92+
* \return map of service names and their types
93+
*/
94+
RVIZ_COMMON_PUBLIC
95+
std::map<std::string, std::vector<std::string>>
96+
get_service_names_and_types() const override;
97+
8898
// TODO(wjwwood): think about a suitable way to extend the abstraction to also cover subscriptions
8999
RVIZ_COMMON_PUBLIC
90100
rclcpp::Node::SharedPtr

rviz_common/include/rviz_common/ros_integration/ros_node_abstraction_iface.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class RosNodeAbstractionIface
5656
virtual std::map<std::string, std::vector<std::string>>
5757
get_topic_names_and_types() const = 0;
5858

59+
virtual std::map<std::string, std::vector<std::string>>
60+
get_service_names_and_types() const = 0;
61+
5962
// TODO(anhosi): remove once the RosNodeAbstraction is extended to handle subscriptions
6063
// and clock
6164
virtual rclcpp::Node::SharedPtr
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// Copyright (c) 2025, Open Source Robotics Foundation, Inc.
2+
// All rights reserved.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// * Redistributions of source code must retain the above copyright
8+
// notice, this list of conditions and the following disclaimer.
9+
//
10+
// * Redistributions in binary form must reproduce the above copyright
11+
// notice, this list of conditions and the following disclaimer in the
12+
// documentation and/or other materials provided with the distribution.
13+
//
14+
// * Neither the name of the copyright holder nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
// POSSIBILITY OF SUCH DAMAGE.
29+
30+
#include <map>
31+
#include <memory>
32+
#include <string>
33+
#include <vector>
34+
35+
#include <QApplication> // NOLINT: cpplint can't handle Qt imports
36+
#include <QObject> // NOLINT: cpplint can't handle Qt imports
37+
#include <QRegExp> // NOLINT: cpplint can't handle Qt imports
38+
#include <QString> // NOLINT: cpplint can't handle Qt imports
39+
#include <QStringList> // NOLINT: cpplint can't handle Qt imports
40+
41+
#include "rviz_common/properties/ros_service_property.hpp"
42+
#include "rviz_common/ros_integration/ros_node_abstraction_iface.hpp"
43+
44+
namespace rviz_common
45+
{
46+
namespace properties
47+
{
48+
49+
RosServiceProperty::RosServiceProperty(
50+
const QString & name,
51+
const QString & default_value,
52+
const QString & service_type,
53+
const QString & description,
54+
Property * parent,
55+
const char * changed_slot,
56+
QObject * receiver)
57+
: EditableEnumProperty(name, default_value, description, parent, changed_slot, receiver),
58+
rviz_ros_node_(),
59+
service_type_(service_type)
60+
{
61+
connect(
62+
this, SIGNAL(requestOptions(EditableEnumProperty*)),
63+
this, SLOT(fillServiceList()));
64+
}
65+
66+
void RosServiceProperty::initialize(ros_integration::RosNodeAbstractionIface::WeakPtr rviz_ros_node)
67+
{
68+
rviz_ros_node_ = rviz_ros_node;
69+
}
70+
71+
void RosServiceProperty::setServiceType(const QString & service_type)
72+
{
73+
service_type_ = service_type;
74+
}
75+
76+
QString RosServiceProperty::getServiceType() const
77+
{
78+
return service_type_;
79+
}
80+
81+
QString RosServiceProperty::getService() const
82+
{
83+
return getValue().toString();
84+
}
85+
86+
std::string RosServiceProperty::getServiceStd() const
87+
{
88+
return getValue().toString().toStdString();
89+
}
90+
91+
bool RosServiceProperty::isEmpty() const
92+
{
93+
return getServiceStd().empty();
94+
}
95+
96+
void RosServiceProperty::fillServiceList()
97+
{
98+
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
99+
clearOptions();
100+
101+
std::string std_service_type = service_type_.toStdString();
102+
std::map<std::string, std::vector<std::string>> service_servers =
103+
rviz_ros_node_.lock()->get_service_names_and_types();
104+
105+
for (const auto & service : service_servers) {
106+
// Only add service whose type matches.
107+
for (const auto & type : service.second) {
108+
if (type == std_service_type) {
109+
addOptionStd(service.first);
110+
}
111+
}
112+
}
113+
sortOptions();
114+
QApplication::restoreOverrideCursor();
115+
}
116+
117+
RosFilteredServiceProperty::RosFilteredServiceProperty(
118+
const QString & name,
119+
const QString & default_value,
120+
const QString & service_type,
121+
const QString & description,
122+
const QRegExp & filter,
123+
Property * parent,
124+
const char * changed_slot,
125+
QObject * receiver)
126+
: RosServiceProperty(name, default_value, service_type, description, parent, changed_slot, receiver)
127+
, filter_(filter)
128+
, filter_enabled_(true)
129+
{
130+
}
131+
132+
void RosFilteredServiceProperty::enableFilter(bool enabled)
133+
{
134+
filter_enabled_ = enabled;
135+
fillServiceList();
136+
}
137+
138+
QRegExp RosFilteredServiceProperty::filter() const
139+
{
140+
return filter_;
141+
}
142+
143+
void RosFilteredServiceProperty::fillServiceList()
144+
{
145+
QStringList filtered_strings_;
146+
147+
// Obtain list of available services
148+
RosServiceProperty::fillServiceList();
149+
// Apply filter
150+
if (filter_enabled_) {
151+
strings_ = strings_.filter(filter_);
152+
}
153+
}
154+
} // end namespace properties
155+
} // end namespace rviz_common

rviz_common/src/rviz_common/ros_integration/ros_node_abstraction.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,11 @@ RosNodeAbstraction::get_topic_names_and_types() const
6262
return raw_node_->get_topic_names_and_types();
6363
}
6464

65+
std::map<std::string, std::vector<std::string>>
66+
RosNodeAbstraction::get_service_names_and_types() const
67+
{
68+
return raw_node_->get_service_names_and_types();
69+
}
70+
6571
} // namespace ros_integration
6672
} // namespace rviz_common

0 commit comments

Comments
 (0)