@@ -23,75 +23,148 @@ class ROSServiceProxyBase
23
23
24
24
// ! Abstract ROS Service Server Proxy
25
25
class ROSServiceServerProxyBase : public ROSServiceProxyBase
26
- {
26
+ {
27
27
public:
28
28
ROSServiceServerProxyBase (const std::string &service_name) :
29
- ROSServiceProxyBase (service_name),
30
- proxy_operation_caller_ ()
29
+ ROSServiceProxyBase (service_name)
31
30
{ }
32
-
31
+
33
32
// ! Connect an RTT Operation to this ROS service server
34
- bool connect (RTT::TaskContext *owner, RTT::OperationInterfacePart* operation) {
35
- // Link the caller with the operation
36
- return proxy_operation_caller_->setImplementation (
37
- operation->getLocalOperation (),
38
- RTT::internal::GlobalEngine::Instance ());
39
- }
33
+ virtual bool connect (RTT::TaskContext *owner, RTT::OperationInterfacePart* operation) = 0;
40
34
41
35
protected:
42
36
// ! The underlying ROS service server
43
37
ros::ServiceServer server_;
44
- // ! The underlying RTT operation caller
45
- boost::shared_ptr<RTT::base::OperationCallerBaseInvoker> proxy_operation_caller_;
46
38
};
47
39
48
40
template <class ROS_SERVICE_T >
49
- class ROSServiceServerProxy : public ROSServiceServerProxyBase
50
- {
41
+ class ROSServiceServerOperationCallerBase {
42
+ public:
43
+ typedef boost::shared_ptr<ROSServiceServerOperationCallerBase<ROS_SERVICE_T> > Ptr ;
44
+ virtual ~ROSServiceServerOperationCallerBase () {}
45
+ virtual bool call (typename ROS_SERVICE_T::Request& request, typename ROS_SERVICE_T::Response& response) const = 0;
46
+ };
47
+
48
+ template <class ROS_SERVICE_T , int variant = 0 >
49
+ struct ROSServiceServerOperationCallerWrapper ;
50
+
51
+ // Default implementation of an OperationCaller that fowards ROS service calls to Orocos operations
52
+ // that have the default bool(Request&, Response&) signature. You can add more variants of this class
53
+ // to add support for custom operation types.
54
+ //
55
+ // See package std_srvs for an example.
56
+ //
57
+ template <class ROS_SERVICE_T >
58
+ struct ROSServiceServerOperationCallerWrapper <ROS_SERVICE_T,0 > {
59
+ typedef bool Signature (typename ROS_SERVICE_T::Request&, typename ROS_SERVICE_T::Response&);
60
+ typedef RTT::OperationCaller<Signature> ProxyOperationCallerType;
61
+ template <typename Callable> static bool call (Callable& call, typename ROS_SERVICE_T::Request& request, typename ROS_SERVICE_T::Response& response) {
62
+ return call (request, response);
63
+ }
64
+ };
65
+
66
+ template <class ROS_SERVICE_T , int variant = 0 >
67
+ class ROSServiceServerOperationCaller : public ROSServiceServerOperationCallerBase <ROS_SERVICE_T> {
68
+ public:
69
+ using typename ROSServiceServerOperationCallerBase<ROS_SERVICE_T>::Ptr ;
70
+
71
+ // ! The wrapper type for this variant
72
+ typedef ROSServiceServerOperationCallerWrapper<ROS_SERVICE_T, variant> Wrapper;
73
+
74
+ // ! Default operation caller for a ROS service server proxy
75
+ typedef typename Wrapper::ProxyOperationCallerType ProxyOperationCallerType;
76
+ typedef boost::shared_ptr<ProxyOperationCallerType> ProxyOperationCallerTypePtr;
77
+
78
+ private:
79
+ template <typename Dummy> struct Void { typedef void type; };
80
+
81
+ template <typename R = void , typename Enabled = void > struct EnableIfHasNextVariant { };
82
+
83
+ template <typename R> struct EnableIfHasNextVariant <R,
84
+ typename Void<typename ROSServiceServerOperationCallerWrapper<ROS_SERVICE_T, variant + 1 >::ProxyOperationCallerType>::type> {
85
+ typedef R type;
86
+ };
87
+
88
+ template <typename R = void , typename Enabled = void >
89
+ struct NextVariant {
90
+ static Ptr connect (RTT::OperationInterfacePart*) { return Ptr (); }
91
+ };
92
+
93
+ template <typename R>
94
+ struct NextVariant <R, typename EnableIfHasNextVariant<R>::type> {
95
+ static Ptr connect (RTT::OperationInterfacePart* operation) {
96
+ return ROSServiceServerOperationCaller<ROS_SERVICE_T, variant + 1 >::connect (operation);
97
+ }
98
+ };
99
+
51
100
public:
52
- // ! Operation caller for a ROS service server proxy
53
- typedef RTT::OperationCaller<bool (typename ROS_SERVICE_T::Request&, typename ROS_SERVICE_T::Response&)> ProxyOperationCallerType;
101
+ static Ptr connect (RTT::OperationInterfacePart* operation) {
102
+ ProxyOperationCallerTypePtr proxy_operation_caller
103
+ = boost::make_shared<ProxyOperationCallerType>(operation->getLocalOperation (), RTT::internal::GlobalEngine::Instance ());
104
+ if (proxy_operation_caller->ready ()) {
105
+ return Ptr (new ROSServiceServerOperationCaller<ROS_SERVICE_T, variant>(proxy_operation_caller));
106
+ }
107
+ return NextVariant<void >::connect (operation);
108
+ }
109
+
110
+ virtual bool call (typename ROS_SERVICE_T::Request& request, typename ROS_SERVICE_T::Response& response) const {
111
+ // Check if the operation caller is ready, and then call it.
112
+ if (!proxy_operation_caller_->ready ()) return false ;
113
+ return Wrapper::call (*proxy_operation_caller_, request, response);
114
+ }
115
+
116
+ ROSServiceServerOperationCaller (const boost::shared_ptr<ProxyOperationCallerType>& impl)
117
+ : proxy_operation_caller_(impl) {}
118
+
119
+ ProxyOperationCallerTypePtr proxy_operation_caller_;
120
+ };
54
121
122
+ template <class ROS_SERVICE_T >
123
+ class ROSServiceServerProxy : public ROSServiceServerProxyBase
124
+ {
125
+ public:
55
126
/* * \brief Construct a ROS service server and associate it with an Orocos
56
127
* task's required interface and operation caller.
57
128
*/
58
129
ROSServiceServerProxy (const std::string &service_name) :
59
130
ROSServiceServerProxyBase (service_name)
60
131
{
61
- // Construct operation caller
62
- proxy_operation_caller_.reset (new ProxyOperationCallerType (" ROS_SERVICE_SERVER_PROXY" ));
63
-
64
132
// Construct the ROS service server
65
133
ros::NodeHandle nh;
66
134
server_ = nh.advertiseService (
67
- service_name,
68
- &ROSServiceServerProxy<ROS_SERVICE_T>::ros_service_callback,
135
+ service_name,
136
+ &ROSServiceServerProxy<ROS_SERVICE_T>::ros_service_callback,
69
137
this );
70
138
}
71
139
72
140
~ROSServiceServerProxy ()
73
141
{
74
142
// Clean-up advertized ROS services
75
- server_.shutdown ();
143
+ server_.shutdown ();
144
+ }
145
+
146
+ virtual bool connect (RTT::TaskContext *, RTT::OperationInterfacePart* operation)
147
+ {
148
+ impl_ = ROSServiceServerOperationCaller<ROS_SERVICE_T>::connect (operation);
149
+ return (impl_.get () != 0 );
76
150
}
77
151
78
152
private:
79
-
80
153
// ! The callback called by the ROS service server when this service is invoked
81
154
bool ros_service_callback (typename ROS_SERVICE_T::Request& request, typename ROS_SERVICE_T::Response& response) {
82
- // Downcast the proxy operation caller
83
- ProxyOperationCallerType &proxy_operation_caller = *dynamic_cast <ProxyOperationCallerType*>(proxy_operation_caller_.get ());
84
- // Check if the operation caller is ready, and then call it
85
- return proxy_operation_caller_->ready () && proxy_operation_caller (request, response);
155
+ if (!impl_) return false ;
156
+ return impl_->call (request, response);
86
157
}
158
+
159
+ boost::shared_ptr<ROSServiceServerOperationCallerBase<ROS_SERVICE_T> > impl_;
87
160
};
88
161
89
162
90
163
// ! Abstract ROS Service Client Proxy
91
164
class ROSServiceClientProxyBase : public ROSServiceProxyBase
92
165
{
93
166
public:
94
- ROSServiceClientProxyBase (const std::string &service_name) :
167
+ ROSServiceClientProxyBase (const std::string &service_name) :
95
168
ROSServiceProxyBase (service_name),
96
169
proxy_operation_ ()
97
170
{ }
@@ -107,12 +180,12 @@ class ROSServiceClientProxyBase : public ROSServiceProxyBase
107
180
protected:
108
181
// ! The underlying ROS service client
109
182
ros::ServiceClient client_;
110
- // ! The underlying RTT operation
183
+ // ! The underlying RTT operation
111
184
boost::shared_ptr<RTT::base::OperationBase> proxy_operation_;
112
185
};
113
186
114
187
template <class ROS_SERVICE_T >
115
- class ROSServiceClientProxy : public ROSServiceClientProxyBase
188
+ class ROSServiceClientProxy : public ROSServiceClientProxyBase
116
189
{
117
190
public:
118
191
@@ -122,7 +195,7 @@ class ROSServiceClientProxy : public ROSServiceClientProxyBase
122
195
ROSServiceClientProxy (const std::string &service_name) :
123
196
ROSServiceClientProxyBase (service_name)
124
197
{
125
- // Construct a new
198
+ // Construct a new
126
199
proxy_operation_.reset (new ProxyOperationType (" ROS_SERVICE_CLIENT_PROXY" ));
127
200
128
201
// Construct the underlying service client
@@ -137,7 +210,7 @@ class ROSServiceClientProxy : public ROSServiceClientProxyBase
137
210
}
138
211
139
212
private:
140
-
213
+
141
214
// ! The callback for the RTT operation
142
215
bool orocos_operation_callback (typename ROS_SERVICE_T::Request& request, typename ROS_SERVICE_T::Response& response) {
143
216
// Make sure the ROS service client exists and then call it (blocking)
@@ -147,7 +220,7 @@ class ROSServiceClientProxy : public ROSServiceClientProxyBase
147
220
148
221
149
222
// ! Abstract factory for ROS Service Proxy Factories
150
- class ROSServiceProxyFactoryBase
223
+ class ROSServiceProxyFactoryBase
151
224
{
152
225
public:
153
226
@@ -166,7 +239,7 @@ class ROSServiceProxyFactoryBase
166
239
};
167
240
168
241
template <class ROS_SERVICE_T >
169
- class ROSServiceProxyFactory : public ROSServiceProxyFactoryBase
242
+ class ROSServiceProxyFactory : public ROSServiceProxyFactoryBase
170
243
{
171
244
public:
172
245
0 commit comments